//---------------------------------------------------------------------------- // EgalTech 2022 //---------------------------------------------------------------------------- // File : SceneGlobCube.cpp Data : 10.10.22 Versione : 1 // Contenuto : Implementazione gestione e disegno Cubetto per viste. // // // // Modifiche : 11.10.22 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "Scene.h" #include "EGrUtils.h" #include "ObjOldGraphics.h" #include "ObjNewGraphics.h" #include "ObjMultiGraphics.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkObjGraphics.h" using namespace std ; // posizione X e Y dello schermo const double MIN_EDGE_SIZE = 20 ; const double MAX_EDGE_SIZE = 200.0 ; // colore render dei bordi delle superifici del cubo const Color CUBE_LINES( 0, 0, 0, 1) ; // angolo di tolleranza per rotazioni con vettori quasi paralleli const double ANG_ROT_TOLL = 5 ; //---------------------------------------------------------------------------- bool Scene::CreateFlatPart( ISurfTriMesh* pSrf) { // vertici pSrf->AddVertex( Point3d( 0.33 * m_dCubeEdge, 0.33 * m_dCubeEdge, 0)), pSrf->AddVertex( Point3d( - 0.33 * m_dCubeEdge, 0.33 * m_dCubeEdge, 0)) ; pSrf->AddVertex( Point3d( - 0.33 * m_dCubeEdge, - 0.33 * m_dCubeEdge, 0)) ; pSrf->AddVertex( Point3d( 0.33 * m_dCubeEdge, - 0.33 * m_dCubeEdge, 0)) ; // triangoli int nNewInd_0[3] = { 0, 1, 2} ; pSrf->AddTriangle( nNewInd_0) ; int nNewInd_1[3] = { 0, 2, 3} ; pSrf->AddTriangle( nNewInd_1) ; // verifico pSrf->DoCompacting() ; return true ; } //---------------------------------------------------------------------------- bool Scene::CreateEdgePart( ISurfTriMesh* pSrf) { // vertici pSrf->AddVertex( Point3d( 0.33 * m_dCubeEdge, - 0.085 * m_dCubeEdge, 0)) ; pSrf->AddVertex( Point3d( - 0.33 * m_dCubeEdge, - 0.085 * m_dCubeEdge, 0)) ; pSrf->AddVertex( Point3d( - 0.33 * m_dCubeEdge, 0, - 0.085 * m_dCubeEdge)) ; pSrf->AddVertex( Point3d( 0.33 * m_dCubeEdge, 0, - 0.085 * m_dCubeEdge)) ; pSrf->AddVertex( Point3d( - 0.33 * m_dCubeEdge, 0.085 * m_dCubeEdge, - 0.17 * m_dCubeEdge)) ; pSrf->AddVertex( Point3d( 0.33 * m_dCubeEdge, 0.085 * m_dCubeEdge, - 0.17 * m_dCubeEdge)) ; // triangoli int nNewInd_0[3] = { 2, 1 ,0} ; pSrf->AddTriangle( nNewInd_0) ; int nNewInd_1[3] = { 3, 2, 0} ; pSrf->AddTriangle( nNewInd_1) ; int nNewInd_2[3] = { 2, 5, 4} ; pSrf->AddTriangle( nNewInd_2) ; int nNewInd_3[3] = { 2, 3, 5} ; pSrf->AddTriangle( nNewInd_3) ; // verifico pSrf->DoCompacting() ; return true ; } //---------------------------------------------------------------------------- bool Scene::CreateCornerPart( ISurfTriMesh* pSrf) { // vertici pSrf->AddVertex( Point3d( - 0.085 * m_dCubeEdge, 0.085 * m_dCubeEdge, -0.17 * m_dCubeEdge)) ; pSrf->AddVertex( Point3d( - 0.085 * m_dCubeEdge, - 0.085 * m_dCubeEdge, 0)) ; pSrf->AddVertex( Point3d( 0.085 * m_dCubeEdge, - 0.085 * m_dCubeEdge, - 0.17 * m_dCubeEdge)) ; // triangoli int nNewInd_0[3] = { 0, 1, 2} ; pSrf->AddTriangle( nNewInd_0) ; // verifico pSrf->DoCompacting() ; return true ; } //---------------------------------------------------------------------------- static ObjEGrGraphics* CreateObjEGrGraphics( int nCount, bool bNewWay) { if ( nCount > 1) return ( new( nothrow) ObjMultiGraphics( nCount, bNewWay)) ; else if ( bNewWay) return ( new( nothrow) ObjNewGraphics) ; else return ( new( nothrow) ObjOldGraphics) ; } //---------------------------------------------------------------------------- bool Scene::DrawCube( bool bSurf) { // recupero la matrice viewport GLint Viewport[4] ; glGetIntegerv( GL_VIEWPORT, Viewport) ; // se il vettore delle superifici è vuoto, allora lo creo if ( m_vStm_Cube.empty()) { // Z+ -> 1 -> TOP PtrOwner pStm_Zp( CreateSurfTriMesh()) ; CreateFlatPart( pStm_Zp) ; pStm_Zp->Translate( Vector3d( 0, 0, 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_Zp)) ; // Z- -> 2 -> BOTTOM PtrOwner pStm_Zm( CreateSurfTriMesh()) ; CreateFlatPart( pStm_Zm) ; pStm_Zm->Rotate( ORIG, Y_AX, 180) ; pStm_Zm->Translate( Vector3d( 0, 0, - 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_Zm)) ; // X+ -> 3 -> RIGHT PtrOwner pStm_Xp( CreateSurfTriMesh()) ; CreateFlatPart( pStm_Xp) ; pStm_Xp->Rotate( ORIG, Y_AX, 180) ; pStm_Xp->Rotate( ORIG, -Y_AX, 90) ; pStm_Xp->Translate( Vector3d( 0.5 * m_dCubeEdge, 0, 0)) ; m_vStm_Cube.emplace_back( Release( pStm_Xp)) ; // X- -> 4 -> LEFT PtrOwner pStm_Xm( CreateSurfTriMesh()) ; CreateFlatPart( pStm_Xm) ; pStm_Xm->Rotate( ORIG, -Y_AX, 90) ; pStm_Xm->Translate( Vector3d( -0.5 * m_dCubeEdge, 0, 0)) ; m_vStm_Cube.emplace_back( Release( pStm_Xm)) ; // Y+ -> 5 -> FRONT PtrOwner pStm_Yp( CreateSurfTriMesh()) ; CreateFlatPart( pStm_Yp) ; pStm_Yp->Rotate( ORIG, -X_AX, 90) ; pStm_Yp->Translate( Vector3d( 0, 0.5 * m_dCubeEdge, 0)) ; m_vStm_Cube.emplace_back( Release( pStm_Yp)) ; // Y- -> 6 -> BACK PtrOwner pStm_Ym( CreateSurfTriMesh()) ; CreateFlatPart( pStm_Ym) ; pStm_Ym->Rotate( ORIG, Y_AX, 180) ; pStm_Ym->Rotate( ORIG, -X_AX, 90) ; pStm_Ym->Translate( Vector3d( 0, -0.5 * m_dCubeEdge, 0)) ; m_vStm_Cube.emplace_back( Release( pStm_Ym)) ; // Z+X+ -> 7 -> TOP-RIGHT PtrOwner pStm_ZpXp( CreateSurfTriMesh()) ; CreateEdgePart( pStm_ZpXp) ; pStm_ZpXp->Rotate( ORIG, -Z_AX, 90) ; pStm_ZpXp->Translate( Vector3d(( 0.5 - 0.085) * m_dCubeEdge , 0, 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_ZpXp)) ; // Z+X- -> 8 -> TOP-LEFT PtrOwner pStm_ZpXm( CreateSurfTriMesh()) ; CreateEdgePart( pStm_ZpXm) ; pStm_ZpXm->Rotate( ORIG, Z_AX, 90) ; pStm_ZpXm->Translate( Vector3d(( - 0.5 + 0.085) * m_dCubeEdge, 0, 0.5 * m_dCubeEdge)); m_vStm_Cube.emplace_back( Release( pStm_ZpXm)) ; // Z-X+ -> 9 -> BOTTOM-RIGHT PtrOwner pStm_ZmXp( CreateSurfTriMesh()) ; CreateEdgePart( pStm_ZmXp) ; pStm_ZmXp->Rotate( ORIG, -Z_AX, 90) ; pStm_ZmXp->Rotate( ORIG, Y_AX, 90) ; pStm_ZmXp->Translate( Vector3d( 0.5 * m_dCubeEdge, 0,( - 0.5 + 0.085) * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_ZmXp)) ; // Z-X- -> 10 -> BOTTOM-LEFT PtrOwner pStm_ZmXm( CreateSurfTriMesh()) ; CreateEdgePart( pStm_ZmXm) ; pStm_ZmXm->Rotate( ORIG, Z_AX, 90) ; pStm_ZmXm->Rotate( ORIG, -Y_AX, 90) ; pStm_ZmXm->Translate( Vector3d( - 0.5 * m_dCubeEdge, 0, ( - 0.5 + 0.085) * m_dCubeEdge)) ;; m_vStm_Cube.emplace_back( Release( pStm_ZmXm)) ; // Z+Y+ -> 11 -> TOP-FRONT PtrOwner pStm_ZpYp( CreateSurfTriMesh()) ; CreateEdgePart( pStm_ZpYp) ; pStm_ZpYp->Translate( Vector3d( 0, ( 0.5 - 0.085) * m_dCubeEdge, 0.5 * m_dCubeEdge)) ; pStm_ZpYp->SetTempProp( 5, 0) ; m_vStm_Cube.emplace_back( Release( pStm_ZpYp)) ; // Z+Y- -> 12 -> TOP-BACK PtrOwner pStm_ZpYm( CreateSurfTriMesh()) ; CreateEdgePart( pStm_ZpYm) ; pStm_ZpYm->Rotate( ORIG, -Z_AX, 180) ; pStm_ZpYm->Translate( Vector3d( 0, ( - 0.5 + 0.085) * m_dCubeEdge, 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_ZpYm)) ; // Z-Y+ -> 13 -> BOTTOM-FRONT PtrOwner pStm_ZmYp( CreateSurfTriMesh()) ; CreateEdgePart( pStm_ZmYp) ; pStm_ZmYp->Rotate( ORIG, -X_AX, 90) ; pStm_ZmYp->Translate( Vector3d( 0, ( 0.5) * m_dCubeEdge , ( - 0.5 + 0.085) * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_ZmYp)) ; // Z-Y- -> 14 -> BOTTOM-BACK PtrOwner pStm_ZmYm( CreateSurfTriMesh()) ; CreateEdgePart( pStm_ZmYm) ; pStm_ZmYm->Rotate( ORIG, -Z_AX, 180) ; pStm_ZmYm->Rotate( ORIG, X_AX, 90) ; pStm_ZmYm->Translate( Vector3d( 0, - 0.5 * m_dCubeEdge, ( - 0.5 + 0.085) * m_dCubeEdge )) ; m_vStm_Cube.emplace_back( Release( pStm_ZmYm)) ; // X+Y+ -> 15 -> RIGHT-FRONT PtrOwner pStm_XpYp( CreateSurfTriMesh()) ; CreateEdgePart( pStm_XpYp) ; pStm_XpYp->Rotate( ORIG, Y_AX, 90) ; pStm_XpYp->Translate( Vector3d( 0.5 * m_dCubeEdge,( 0.5 - 0.085) * m_dCubeEdge, 0)) ; m_vStm_Cube.emplace_back( Release( pStm_XpYp)) ; // X-Y+ -> 16 -> LEFT-FRONT PtrOwner pStm_XmYp( CreateSurfTriMesh()) ; CreateEdgePart( pStm_XmYp) ; pStm_XmYp->Rotate( ORIG, -Y_AX, 90) ; pStm_XmYp->Translate( Vector3d( - 0.5 * m_dCubeEdge, ( 0.5 - 0.085) * m_dCubeEdge, 0)) ; m_vStm_Cube.emplace_back( Release( pStm_XmYp)) ; // X+Y- -> 17 -> RIGHT-BACK PtrOwner pStm_XpYm( CreateSurfTriMesh()) ; CreateEdgePart( pStm_XpYm) ; pStm_XpYm->Rotate( ORIG, -Y_AX, 90) ; pStm_XpYm->Rotate( ORIG, Z_AX, 180) ; pStm_XpYm->Translate( Vector3d( 0.5 * m_dCubeEdge, ( - 0.5 + 0.085) * m_dCubeEdge , 0)) ; m_vStm_Cube.emplace_back( Release( pStm_XpYm)) ; // X-Y- -> 18 -> LEFT-BACK PtrOwner pStm_XmYm( CreateSurfTriMesh()) ; CreateEdgePart( pStm_XmYm) ; pStm_XmYm->Rotate( ORIG, Y_AX, 90) ; pStm_XmYm->Rotate( ORIG, Z_AX, 180) ; pStm_XmYm->Translate( Vector3d( - 0.5 * m_dCubeEdge,- ( 0.5 - 0.085) * m_dCubeEdge, 0)) ; m_vStm_Cube.emplace_back( Release( pStm_XmYm)) ; // Z+X+Y+ -> 19 -> TOP-RIGHT-FRONT PtrOwner pStm_XpYpZp( CreateSurfTriMesh()) ; CreateCornerPart( pStm_XpYpZp ) ; pStm_XpYpZp->Translate( Vector3d(( 0.5 - 0.085) * m_dCubeEdge, ( 0.5 - 0.085) * m_dCubeEdge, 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_XpYpZp)) ; // Z+X-Y+ -> 20 -> TOP-LEFT-FRONT PtrOwner pStm_XmYpZp( CreateSurfTriMesh()) ; CreateCornerPart( pStm_XmYpZp) ; pStm_XmYpZp->Rotate( ORIG, Z_AX, 90) ; pStm_XmYpZp->Translate( Vector3d(( - 0.5 + 0.085) * m_dCubeEdge,( 0.5 - 0.085) * m_dCubeEdge,0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_XmYpZp)) ; // Z+X+Y- -> 21 -> TOP-RIGHT-BACK PtrOwner pStm_XpYmZp( CreateSurfTriMesh()) ; CreateCornerPart( pStm_XpYmZp) ; pStm_XpYmZp->Rotate( ORIG, -Z_AX, 90) ; pStm_XpYmZp->Translate( Vector3d(( + 0.5 - 0.085) * m_dCubeEdge, ( - 0.5 + 0.085) * m_dCubeEdge,0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_XpYmZp)) ; // Z+X-Y- -> 22 -> TOP-LEFT-BACK PtrOwner pStm_XmYmZp( CreateSurfTriMesh()) ; CreateCornerPart( pStm_XmYmZp) ; pStm_XmYmZp->Rotate( ORIG, Z_AX, 180) ; pStm_XmYmZp->Translate( Vector3d(( - 0.5 + 0.085) * m_dCubeEdge, ( - 0.5 + 0.085) * m_dCubeEdge, 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_XmYmZp)) ; // Z-X+Y+ -> 23 -> BOTTOM-RIGHT-FRONT PtrOwner pStm_XpYpZm( CreateSurfTriMesh()) ; CreateCornerPart( pStm_XpYpZm) ; pStm_XpYpZm->Rotate( ORIG, X_AX, 180) ; pStm_XpYpZm->Rotate( ORIG, Z_AX, 90) ; pStm_XpYpZm->Translate( Vector3d(( 0.5 - 0.085) * m_dCubeEdge, ( 0.5 - 0.085) * m_dCubeEdge, - 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_XpYpZm)) ; // Z-X-Y+ -> 24 -> BOTTOM-LEFT-FRONT PtrOwner pStm_XmYpZm( CreateSurfTriMesh()) ; CreateCornerPart( pStm_XmYpZm) ; pStm_XmYpZm->Rotate(ORIG, -X_AX, 90) ; pStm_XmYpZm->Rotate( ORIG, Z_AX, 90) ; pStm_XmYpZm->Translate( Vector3d( - 0.5 * m_dCubeEdge, ( 0.5 - 0.085) * m_dCubeEdge,( - 0.5 + 0.085) * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_XmYpZm)) ; // Z-X+Y- -> 25 -> BOTTOM-RIGHT-BACK PtrOwner pStm_XpYmZm( CreateSurfTriMesh()) ; CreateCornerPart( pStm_XpYmZm) ; pStm_XpYmZm->Rotate( ORIG, X_AX, 180) ; pStm_XpYmZm->Translate( Vector3d(( + 0.5 - 0.085) * m_dCubeEdge, ( - 0.5 + 0.085) * m_dCubeEdge, - 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_XpYmZm)) ; // Z-X-Y- -> 26 -> BOTTOM-LEFT-BACK PtrOwner pStm_XmYmZm( CreateSurfTriMesh()) ; CreateCornerPart( pStm_XmYmZm) ; pStm_XmYmZm->Rotate( ORIG, X_AX, 180) ; pStm_XmYmZm->Rotate( ORIG, -Z_AX, 90) ; pStm_XmYmZm->Translate( Vector3d(( - 0.5 + 0.085) * m_dCubeEdge, ( - 0.5 + 0.085) * m_dCubeEdge, - 0.5 * m_dCubeEdge)) ; m_vStm_Cube.emplace_back( Release( pStm_XmYmZm)) ; } // creo un vettore di Graphics, uno per ogni superificie del cubetto vector> vGraphics ; for ( int i = 0 ; i < 26 ; ++ i) { PtrOwner pNewGraphics( CreateObjEGrGraphics( 0, false)) ; vGraphics.emplace_back( Release( pNewGraphics)) ; vGraphics[i]->SetScene( this) ; } // render delle superifici del cubo ( superfici o Linee a seconda del Flag) for ( int s = 0 ; s < 26 ; ++ s) { // recupero la superificie corrente del cubo da visualizzare PtrOwner pStmCurr( CloneSurfTriMesh( m_vStm_Cube[s])) ; if ( IsNull( pStmCurr)) return false ; // scalo la superificie a seconda della viewport corrente ( per Zoom) pStmCurr->Scale( GLOB_FRM, ( 2 * m_dHalfWidth) / Viewport[2], ( 2 * m_dHalfWidth) / Viewport[2], ( 2 * m_dHalfWidth) / Viewport[2]) ; // sposto la superificie nel sistema di riferimento relativo alla telecamera ( per Pan) pStmCurr->Translate(( m_ptOrigCube - ORIG)) ; // definisco colori per i vertici e colore per le linee Color cCol_Vertex ; Color cCol_Line = CUBE_LINES ; switch ( s) { case 0 : cCol_Vertex = m_cColZ ; break ; case 1 : cCol_Vertex = m_cColZm ; break ; case 2 : cCol_Vertex = m_cColX ; break ; case 3 : cCol_Vertex = m_cColXm ; break ; case 4 : cCol_Vertex = m_cColY ; break ; case 5 : cCol_Vertex = m_cColYm ; break ; break ; case 6 : case 7 : case 8 : case 9 : case 10 : case 11 : case 12 : case 13 : case 14 : case 15 : case 16 : case 17 : cCol_Vertex = m_cColEdge ; break ; case 18 : case 19 : case 20 : case 21: case 22: case 23 : case 24 : case 25 : cCol_Vertex = m_cColCorner ; break ; default : break ; } vGraphics[s]->AddColor( bSurf ? cCol_Vertex : CUBE_LINES) ; int nTria = pStmCurr->GetTriangleCount() ; vGraphics[s]->StartTriangles( nTria) ; Triangle3dEx Tria ; int nId = pStmCurr->GetFirstTriangle( Tria) ; while ( nId != SVT_NULL) { // edge solo se boundary e normali ai vertici smussate vGraphics[s]->AddTriangle( Tria, Tria.GetTriFlags(), Tria.GetTriNormals()) ; nId = pStmCurr->GetNextTriangle( nId, Tria) ; } vGraphics[s]->EndTriangles() ; // assegno un id temporaneo alla superificie caricata ( modalita wireFrame, come nella Select) if ( ! bSurf) glLoadName( m_nStartFaceId + s + 1) ; vGraphics[s]->Draw( GDB_ST_ON, GDB_MK_OFF, true, true, 80, false) ; } return true ; } //---------------------------------------------------------------------------- bool Scene::DrawGlobCube( bool bSurf) { // se non devo disegnare il cubetto, esco if ( ! m_bShowGlobCube) return true ; // recupero il primo Id libero ( e aggiungo 1000) m_nStartFaceId = m_pGeomDB->GetNewId() + 1000 ; // recupero la matrice viewport GLint Viewport[4] ; glGetIntegerv( GL_VIEWPORT, Viewport) ; // imposto il riferimento glPushMatrix() ; // se sono in selezione il cubo lo lascio nella posizione precedente ( cambio di viewport => cambio centro del cubo) Point3d ptOrig ; if ( m_bSelect) ptOrig = m_ptOrigCube ; else { UnProject( Point3d( m_dCubeX, m_dCubeY, 0.25), ptOrig) ; // posizione Z del cubo sempre 0.25 dallo schermo m_ptOrigCube = ptOrig ; } // creo il cubo if ( ! DrawCube( bSurf)) return true ; // tolgo lo stack dei nomi in modalità selezione if ( m_bSelect) glLoadName( 0) ; // ripristino lo stack delle matrici glPopMatrix() ; return true ; } //---------------------------------------------------------------------------- bool Scene::RotateCameraWithCube() { // controllo se il cubetto è abilitato e ho almeno un Id dalla selezione nel buffer if ( ! m_bShowGlobCube || m_nSelNbr == 0) return false ; // controllo che la selezione non sia avvenuta mediante Drag if ( m_nSelW != 13 || m_nSelH != 13) return false ; // se ho più di un elemento trovato, do priorità alla superificie con più facce int nId = 0 ; int nFace = 1 ; bool bSelStm_Cube = false ; for ( int i = 0 ; i < m_nSelNbr ; ++ i) { // recupero l'Id corrente int nCurrId = m_nSelBuff[i].nId ; // controllo che l'Id appartenga ad una superificie del cubetto if ( nCurrId <= m_nStartFaceId || nCurrId > m_nStartFaceId + 26) continue ; bSelStm_Cube = true ; int nCurrFace = 1 ; if ( nCurrId - m_nStartFaceId > 6 && nCurrId - m_nStartFaceId <= 18) // se superificie Edge nCurrFace = 2 ; else if ( nCurrId - m_nStartFaceId > 18) // se superificie Corner nCurrFace = 3 ; nFace = max( nFace, nCurrFace) ; if ( nFace == 1 || nFace == nCurrFace) nId = nCurrId ; } if ( ! bSelStm_Cube) return false ; // ottengo la faccia del cubo selezionato ( valore tra 1 e 26) int nCubeface = nId - m_nStartFaceId ; // prendo i parametri della telecamera double dTheta, dPhi, dDist ; GetCamera( &dPhi, &dTheta, &dDist) ; double dPhi_orig = dPhi ; double dTheta_orig = dTheta ; // flag per numero di Step fatti e valore forzato di Theta per Z+ e Z- bool bHasTwoStep = false ; double dTheta_Forced = 0.0 ; // imposto i nuovi angoli theta e phi mantenendo la distanza if ( GetAngleByCubeFace( nCubeface, dTheta, dPhi)) { // ricavo il vettore iniziale della telecamera Vector3d v_q1 = m_vtDirCamera ; // ricavo il vettore finale della telecamera Vector3d v_q2 = FromSpherical( 1 , dPhi, dTheta) ; // flag per rotazione necessaria o superflua bool bDoRotation = true ; // nuovi angoli nel caso di doppie rotazioni double dTheta_new ; double dPhi_new ; // controllo se voglio mettere la vista in Z+ o Z- if ( AreSameOrOppositeVectorApprox( v_q2, Z_AX)) { // controllo se sono già in posizione questa posizione ( Z+ o Z-) if ( AreSameVectorApprox( v_q1, v_q2)) { // se sono già orientato in maniera corretta non faccio nulla, altrimenti... if ( abs( dTheta_orig - ( ANG_RIGHT - ANG_STRAIGHT)) > EPS_ANG_SMALL) { Vector3d v_q1S = FromSpherical( 1, 90, dTheta_orig) ; // ... ruoto la telecamera solo lungo theta RotateCameraWithBlockedAngle( v_q1S, -Y_AX, dDist, true, 1, dTheta_orig, dPhi_orig, dTheta_new, dPhi_new) ; } bDoRotation = false ; } // se non sono in posizione Z+ o Z- e devo andare in una di queste due, allora... else if ( ! (( v_q2.IsZplus() || v_q2.IsZminus()) && ( abs( dTheta_orig - ( ANG_STRAIGHT + ANG_RIGHT)) < EPS_SMALL && v_q1.y < 0))) { // controllo se sono nel caso limite della faccia quasi opposta bool bForceCoeff = false ; if ( abs( dTheta_orig - ( ANG_RIGHT)) < EPS_ANG_SMALL) v_q1.Rotate( Z_AX, 5) ; bHasTwoStep = true ; // ... ruoto la telecamera solo lungo theta RotateCameraWithBlockedAngle( v_q1, - Y_AX, 1, true, 1, dTheta_orig, dPhi_orig, dTheta_new, dPhi_new) ; dTheta_Forced = ANG_RIGHT + ANG_STRAIGHT ; v_q1 = FromSpherical( 1, dPhi_orig, dTheta_Forced) ; } } // controllo se sono in posizione Z+ o Z- e devo sistemare la vista in un'altra posizione else if ( AreSameOrOppositeVectorApprox( v_q1, Z_AX)) { // ho già controllato di non aver v_q1 e v_q2 paralleli... double dTheta_S, dPhi_S , dLenS_ ; v_q2.ToSpherical( &dLenS_, &dPhi_S, &dTheta_S) ; if ( abs( dTheta_orig - dTheta_S) > EPS_SMALL) { Vector3d v_q1S = FromSpherical( 1, 90, dTheta_orig) ; // controllo nel caso di angoli opposti ( o quasi) bool bForceCoeff = false ; if ( abs( dTheta_S - ANG_RIGHT ) < EPS_ANG_SMALL) { v_q1S.Rotate( Z_AX, dTheta_S - ANG_RIGHT >= 0 ? ANG_ROT_TOLL : -ANG_ROT_TOLL) ; bForceCoeff = true ; } // ... ruoto la telecamera solo lungo theta RotateCameraWithBlockedAngle( v_q1S, v_q2, dDist, bForceCoeff ? 2 : 1, 1, dTheta_orig, dPhi_orig, dTheta_new, dPhi_new) ; dTheta_Forced = dTheta_new ; v_q1 = FromSpherical( 1, dPhi_orig, dTheta_Forced) ; bHasTwoStep = true ; } else { bHasTwoStep = true ; dTheta_Forced = ANG_RIGHT + ANG_STRAIGHT ; } } // se devo ruotare ... animazione mediante Slerp con parametro u tra 0 e 1 if ( bDoRotation) RotateCameraWithBlockedAngle( v_q1, v_q2, dDist, true, bHasTwoStep ? 2 : 0, dTheta_Forced, dPhi_orig, dTheta_new, dPhi_new) ; } // refresh finale per sicurezza RedrawWindow() ; // annullo il numero di elementi selezionati m_nSelNbr = 0 ; return true ; } //---------------------------------------------------------------------------- bool Scene::RotateCameraWithBlockedAngle( Vector3d vDirS, Vector3d vDirE, double dDist, int nAdaptSpeed, int nBlockedAngle, double dTheta_orig, double dPhi_orig, double& dTheta_new, double& dPhi_new) { // controllo dei parametri if ( vDirS.IsSmall() || vDirE.IsSmall() || dDist < EPS_SMALL) return false ; if ( nBlockedAngle < 0 || nBlockedAngle > 2) nBlockedAngle = 0 ; vDirS.Normalize() ; vDirE.Normalize() ; // angolo per interpolazione sferica double dAng = acos( vDirS * vDirE) ; // imposto la velocità di rotazione a seconda dell'angolo da percorrere... ( se richisto, altrimenti 1) int nCoeff = 1 ; if (( nAdaptSpeed == 1 && dAng * RADTODEG > ANG_RIGHT * ( 2.0 / 3.0) - 50 * EPS_ANG_SMALL) || nAdaptSpeed == 2) nCoeff = 2 ; double dThetaSs, dPhiSs, dLenSs, dThetaEs, dPhiEs, dLenEs ; vDirS.ToSpherical( &dLenSs, &dPhiSs, &dThetaSs) ; vDirE.ToSpherical( &dLenEs, &dPhiEs, &dThetaEs) ; if (( abs ( abs( dThetaEs - dThetaSs) - ANG_STRAIGHT)) < 3 * ANG_ROT_TOLL + 5 * EPS_ANG_SMALL) nCoeff = 4 ; // ricavo i parametri per l'interpolazione sferica for ( int u = 0 ; u <= 10 * nCoeff && abs( dAng) > EPS_SMALL ; ++ u) { double du = u ; if ( nCoeff == 2) du = 0.5 * u ; if ( nCoeff == 4) du = 0.25 * u ; Vector3d vSlerp = (( sin( 1 - 0.1 * du) * dAng) / sin( dAng)) * vDirS + ( sin( 0.1 * du * dAng) / sin( dAng)) * vDirE ; double dTheta_u ,dPhi_u ,dLen ; vSlerp.ToSpherical( &dLen, &dPhi_u, &dTheta_u) ; if ( abs( u - 10 * nCoeff) < EPS_SMALL && ( abs( dPhi_u) < EPS_ANG_SMALL || abs( dPhi_u - ANG_STRAIGHT) < EPS_ANG_SMALL)) dTheta_u = ANG_STRAIGHT + ANG_RIGHT ; SetCamera( nBlockedAngle == 1 ? dPhi_orig : dPhi_u, nBlockedAngle == 2 ? dTheta_orig : dTheta_u, dDist) ; RedrawWindow() ; dTheta_new = dTheta_u ; dPhi_new = dPhi_u ; } return true ; } //---------------------------------------------------------------------------- bool Scene::GetAngleByCubeFace( int nFaceId, double &dTheta, double &dPhi) { switch ( nFaceId) { case 1 : // TOP dPhi = 0 ; dTheta = 270 ; break ; case 2 : // BOTTOM dPhi = 180 ; dTheta = 270 ; break ; case 3 : // RIGHT dPhi = 90 ; dTheta = 0 ; break ; case 4 : // LEFT dPhi = 90 ; dTheta = 180 ; break ; case 5 : // FRONT dPhi = 90 ; dTheta = 90 ; break ; case 6 : // BACK dPhi = 90 ; dTheta = 270 ; break ; case 7 : // TOP-RIGHT dPhi = 45 ; dTheta = 0 ; break ; case 8 : // TOP-LEFT dPhi = 45 ; dTheta = 180 ; break ; case 9 : // BOTTOM-RIGHT dPhi = 225 ; dTheta = 180 ; break ; case 10 : // BOTTOM-LEFT dPhi = 225 ; dTheta = 0 ; break ; case 11 : // TOP-FRONT dPhi = 45 ; dTheta = 90 ; break ; case 12 : // TOP-BACK dPhi = 45 ; dTheta = 270 ; break ; case 13 : // BOTTOM-FRONT dPhi = 225 ; dTheta = 270 ; break ; case 14 : // BOTTOM-BACK dPhi = 225 ; dTheta = 90 ; break ; case 15 : // RIGHT-FRONT dPhi = 90 ; dTheta = 45 ; break ; case 16 : // LEFT-FRONT dPhi = 90 ; dTheta = 135 ; break ; case 17 : // RIGHT-BACK dPhi = 90 ; dTheta = 315 ; break ; case 18 : // LEFT-BACK dPhi = 90 ; dTheta = 225 ; break ; case 19 : // TOP-RIGHT-FRONT dPhi = 45 ; dTheta = 45 ; break ; case 20 : // TOP-LEFT-FRONT dPhi = 45 ; dTheta = 135 ; break ; case 21 : // TOP-RIGHT-BACK dPhi = 45 ; dTheta = 315 ; break ; case 22 : // TOP-LEFT-BACK dPhi = 45 ; dTheta = 225 ; break ; case 23 : // BOTTOM-RIGHT-FRONT dPhi = 135 ; dTheta = 45 ; break ; case 24 : // BOTTOM-LEFT-FRONT dPhi = 135 ; dTheta = 135 ; break ; case 25 : // BOTTOM-RIGHT-BACK dPhi = 135 ; dTheta = 315 ; break ; case 26: // BOTTOM-LEFT-BACK dPhi = 135 ; dTheta = 215 ; break ; default : break ; } return true ; } //---------------------------------------------------------------------------- bool Scene::SetGlobCubeParameters( int nPosFlag, double dDistX, double dDistY, double dLenEdge) { // controllo ammissibilità dei parametri if ( nPosFlag < 0 || nPosFlag > 4 || dDistX < 0 || dDistY < 0 || dLenEdge < MIN_EDGE_SIZE || dLenEdge > MAX_EDGE_SIZE ) return false ; // se visualizzazione del cubo non ammessa, esco if ( nPosFlag == 0) { m_bShowGlobCube = false ; return true ; } // imposto il flag di scelta dell'angolo del cubetto m_nCube_Flag = nPosFlag ; // recupero la matrice viewport GLint Viewport[4] ; glGetIntegerv( GL_VIEWPORT, Viewport) ; // imposto le coordinate del centro del cubo ( X e Y coordinate in ViewPort) double dCoordX = 0 ; double dCoordY = 0 ; switch ( m_nCube_Flag) { case 1 : // cubo in alto a destra dCoordX = Viewport[2] - dDistX ; dCoordY = dDistY ; break ; case 2 : // cubo in alto a sinistra dCoordX = dDistX ; dCoordY = dDistY ; break ; case 3 : // cubo in basso a sinistra dCoordX = dDistX ; dCoordY = Viewport[3] - dDistY ; break ; case 4 : // cubo in basso a destra dCoordX = Viewport[2] - dDistX ; dCoordY = Viewport[3] - dDistY ; break ; default : return false ; break ; } // controllo che il cubo stia nella Viewport verticale con l'ingombro del suo lato if ( dCoordX <= sqrt( 3) * dLenEdge * 0.5 * sqrt( 2) * 0.5 + 3 || dCoordX >= Viewport[2] - sqrt( 3) * dLenEdge * 0.5 * sqrt( 2) / 2 - 3) return false ; // controllo che il cubo stia nella Viewport orizzontale con l'ingombro del suo lato if ( dCoordY <= Viewport[1] + sqrt( 3) * dLenEdge * 0.5 * sqrt( 2) * 0.5 + 3 || dCoordY >= Viewport[3] - sqrt( 3) * dLenEdge * 0.5 * sqrt( 2) * 0.5 - 3) return false ; // imposto le variabili membro m_dCubeX = dCoordX ; m_dCubeY = dCoordY ; m_dCubeEdge = dLenEdge ; return true ; }