TAPs 0.7.7.3
TAPsXPolygonalModel.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002 XPolygonalModel.cpp
00003 
00004 (X <==> Extra)
00005 A (Generic) XPolygonal Model
00006 
00007 SUKITTI PUNAK   (11/01/2004)
00008 UPDATE          (05/25/2006)
00009 ******************************************************************************/
00010 #include "TAPsXPolygonalModel.hpp"
00011 // Using Inclusion Model (i.e. definitions are included in declarations)
00012 //                       (this name.cpp is included in name.hpp)
00013 // Each friend is defined directly inside its declaration.
00014 
00015 BEGIN_NAMESPACE_TAPs__OpenGL
00016 //=============================================================================
00017 //-----------------------------------------------------------------------------
00018 // default constructor
00019 template <typename T>
00020 XPolygonalModel<T>::XPolygonalModel ()
00021     : OpenGLMeshModel<T>(),
00022       m_prXVertex( NULL ), m_prFace( NULL ), m_pviVertexRing1List( NULL )
00023 {
00024     #ifdef  TAPs_DEBUG_MODE
00025     std::cout << "XPolygonalModel<" << typeid(T).name() << "> Constructor\n";
00026     #endif//TAPs_ENABLE_DEBUG
00027 }
00028 //-----------------------------------------------------------------------------
00029 // destructor
00030 template <typename T>
00031 XPolygonalModel<T>::~XPolygonalModel ()
00032 {
00033     if ( m_prXVertex != NULL ) {
00034         delete [] m_prXVertex;
00035         m_prXVertex = NULL;
00036     }
00037     if ( m_prFace != NULL ) {
00038         delete [] m_prFace;
00039         m_prFace = NULL;
00040     }
00041     if ( m_pviVertexRing1List != NULL ) {
00042         delete [] m_pviVertexRing1List;
00043         m_pviVertexRing1List = NULL;
00044     }
00045 
00046     #ifdef  TAPs_DEBUG_MODE
00047     std::cout << "XPolygonalModel<" << typeid(T).name() << "> Destructor\n";
00048     #endif//TAPs_ENABLE_DEBUG
00049 }
00050 //-----------------------------------------------------------------------------
00051 // Initialize
00052 template <typename T>
00053 void XPolygonalModel<T>::Initialize ()
00054 {
00055     // Model Initialization
00056     DetermineAndSortRings();
00057     //DetermineFaceRings ();
00058     CalAndSetNormals();
00059     // DetermineAndSortRings();
00060     ApplyMaterial( Enum::FRONT );
00061     //DetermineEdgeList();
00062     CalBoundingAABB();
00063     CalBoundingEllipsoid();
00064     CalBoundingSphere();
00065 }
00066 //-----------------------------------------------------------------------------
00067 // New/Delete Fn
00068 template <typename T>
00069 void XPolygonalModel<T>::NewVertexListByNoVertices ()
00070 {
00071     if ( m_prXVertex != NULL ) {
00072         delete [] m_prXVertex;
00073     }
00074     m_prXVertex = new XVertex<T>[m_iNoVertices];
00075 }
00076 //-----------------------------------------------------------------------------
00077 // New/Delete Fn
00078 template <typename T>
00079 void XPolygonalModel<T>::NewFaceListByNoFaces ()
00080 {
00081     if ( m_prFace != NULL ) {
00082         delete [] m_prFace;
00083     }
00084     m_prFace = new Face<T>[m_iNoFaces];
00085 }
00086 //-----------------------------------------------------------------------------
00087 // Get Half Length
00088 template <typename T>
00089 T XPolygonalModel<T>::GetMaxHalfLength () const
00090 {
00091     T maxHalfSize = 0.0;
00092     for ( int i = 0; i < m_iNoVertices; ++i )
00093     {
00094         if ( fabs( m_prXVertex[i][0] ) > maxHalfSize )
00095             maxHalfSize = fabs( m_prXVertex[i][0] );
00096         if ( fabs( m_prXVertex[i][1] ) > maxHalfSize )
00097             maxHalfSize = fabs( m_prXVertex[i][1] );
00098         if ( fabs( m_prXVertex[i][2] ) > maxHalfSize )
00099             maxHalfSize = fabs( m_prXVertex[i][2] );
00100     }
00101     return maxHalfSize;
00102 }
00103 //-----------------------------------------------------------------------------
00104 // Calculate and set the normals
00105 template <typename T>
00106 void XPolygonalModel<T>::CalAndSetNormals ()
00107 {
00108     CalAndSetFaceNormalsNotNormalized();
00109     DetermineFaceRings();
00110     CalAndSetVertexNormals();
00111     NormalizeFaceNormals();
00112 }
00113 //-----------------------------------------------------------------------------
00114 // Calculate and set the face normals (without normalized)
00115 template <typename T>
00116 inline void XPolygonalModel<T>::CalAndSetFaceNormalsNotNormalized ()
00117 {
00118     // Calculate and set the normal of each face
00119     for ( int i = 0; i < m_iNoFaces; ++i ) {
00120         m_prFace[i].SetNormal(
00121               (   m_prXVertex[ m_prFace[i].GetVertexNo( 1 ) ].GetPosition() 
00122                 - m_prXVertex[ m_prFace[i].GetVertexNo( 0 ) ].GetPosition() )
00123             ^ (   m_prXVertex[ m_prFace[i].GetVertexNo( 2 ) ].GetPosition() 
00124                 - m_prXVertex[ m_prFace[i].GetVertexNo( 1 ) ].GetPosition() )
00125         );
00126     }
00127 }
00128 //-----------------------------------------------------------------------------
00129 // Normalize the face normals
00130 template <typename T>
00131 inline void XPolygonalModel<T>::NormalizeFaceNormals ()
00132 {
00133     for ( int i = 0; i < m_iNoFaces; ++i ) {
00134         const_cast< Vector3<T> * >( &m_prFace[i].GetNormal() )->Normalized();
00135         //m_prFace[i].GetNormal().Normalized();
00136     }
00137 }
00138 //-----------------------------------------------------------------------------
00139 // Determine the ring of each vertex
00140 template <typename T>
00141 inline void XPolygonalModel<T>::DetermineFaceRings ()
00142 {
00143     bool notYetStored;
00144     // Insert the faces contain each vertex
00145     for ( int f = 0; f < m_iNoFaces; ++f ) {
00146         for ( int v = 0; v < m_prFace[f].GetNoVertices(); ++v ) {
00147             notYetStored = true;
00148             for ( int i = 0; i < static_cast<int>(m_prXVertex[m_prFace[f].GetVertexNo(v)].GetFaceRing().size()); ++i ) {
00149                 if ( m_prXVertex[m_prFace[f].GetVertexNo(v)].GetFaceRing()[i] == f ) {
00150                     notYetStored = false;
00151                     break;
00152                 }
00153             }
00154             if ( notYetStored ) {
00155                 m_prXVertex[m_prFace[f].GetVertexNo(v)].GetFaceRing().push_back( f );
00156             }
00157         }
00158     }
00159 }
00160 //-----------------------------------------------------------------------------
00161 // Calculate and set the vertex normals
00162 template <typename T>
00163 inline void XPolygonalModel<T>::CalAndSetVertexNormals ()
00164 {
00165     for ( int v = 0; v < m_iNoVertices; ++v ) {
00166         Vector3<T> vNormal;
00167         for ( int f = 0; f < static_cast<int>( m_prXVertex[v].GetFaceRing().size() ); ++f ) {
00168             vNormal += m_prFace[ m_prXVertex[v].GetFaceRing()[f] ].GetNormal();
00169         }
00170         m_prXVertex[v].SetNormal( vNormal.Normalized() );
00171     }
00172 }
00173 //-----------------------------------------------------------------------------
00174 // Sort the face ring of each vertex
00175 template <typename T>
00176 void XPolygonalModel<T>::DetermineAndSortRings ()
00177 {
00178     #ifdef  TAPs_DEBUG_MODE_DETAIL_1
00179     std::cout << "Xpolygonal Model: Determine and sort the first rings" << std::endl;
00180     #endif//TAPs_DEBUG_MODE_DETAIL_1
00181     //----------------------------------------------------------------
00182     /*  CCW
00183              2 --------- 1
00184             / \         / \
00185            /   \  f_2  /   \
00186           /     \     /     \
00187          /  f_3  \   /  f_1  \
00188         /         \ /         \
00189        3 --------- V --------- 0
00190         \         / \         /
00191          \  f_4  /   \  f_0  /
00192           \     /     \     /
00193            \   /  f_5  \   /
00194             \ /         \ /
00195              4 --------- 5
00196     */
00197     //----------------------------------------------------------------
00198     DetermineFaceRings ();
00199     //----------------------------------------------------------------
00200     // Local Variables
00201     int v, f, i, t1, n, k;
00202     int vertexAt[128];
00203     Face<T> * face;
00204     int lastVertexNo;
00205     //----------------------------------------------------------------
00206     // For each vertex v
00207     m_pviVertexRing1List = new std::vector<int>[m_iNoVertices];
00208     for ( v = 0; v < m_iNoVertices; ++v ) {
00209         //============================================================
00210         // Find the vertex number in each face ring of this vertex
00211         //------------------------------------------------------------
00212         int size = static_cast<int>( m_prXVertex[v].GetFaceRing().size() );
00213         if ( size <= 0 ) {
00214             continue;   // skip this vertex if it doesn't have a face ring
00215         }
00216         int current = 0;
00217         int noOfVertices;
00218         // For each face f in the ring of the vertex v
00219         // find the number of this v vertex in it
00220         for ( f = 0; f < size; ++f ) {
00221             face = &m_prFace[ m_prXVertex[v].GetFaceRing()[f] ];
00222             noOfVertices = face->GetNoVertices();
00223             // Get the number of this v vertex in the f face
00224             // keep the info in vertexAt[f]
00225             for ( i = 0; i < noOfVertices; ++i ) {
00226                 if ( v == face->GetVertexNo(i) ) {
00227                     vertexAt[f] = i;
00228                     break;
00229                 }
00230             }
00231         }
00232         //------------------------------------------------------------
00233         //============================================================
00234         // Arrange the face and vertex rings of this vertex
00235         //------------------------------------------------------------
00236         //------------------------------------------------------------
00237         // Face 0
00238         f = 0;
00239         face = &m_prFace[ m_prXVertex[v].GetFaceRing()[f] ];
00240         lastVertexNo = -1;
00241         // Use the fact that the vertices are listed CCW
00242         for ( i = vertexAt[f]+1; i < face->GetNoVertices(); ++i ) {
00243                 m_pviVertexRing1List[v].push_back( face->GetVertexNo(i) );
00244         }
00245         for ( i = 0; i < vertexAt[f]; ++i ) {
00246                 m_pviVertexRing1List[v].push_back( face->GetVertexNo(i) );
00247         }
00248         lastVertexNo  = ( vertexAt[f]-1 < 0 
00249                         ? face->GetVertexNo( face->GetNoVertices()-1 ) 
00250                         : face->GetVertexNo( vertexAt[f]-1 ) );
00251         //------------------------------------------------------------
00252         // Face 1 to size-1
00253         int iFaceNo;
00254         for ( f = 1; f < size; ++f ) {
00255             // Use the fact that only the next face contains 
00256             // the last inserted vertex to find the next face
00257             i = f;
00258             bool search = true;
00259             while ( i < size && search ) {
00260                 iFaceNo = m_prXVertex[v].GetFaceRing()[i];  // Face#
00261                 face = &m_prFace[ iFaceNo ];            // Face
00262 
00263                 for ( n = 0; n < face->GetNoVertices(); ++n ) {
00264                     if ( lastVertexNo == face->GetVertexNo(n) ) {
00265                         search = false;
00266 
00267                         // Swap (sort) the face
00268                         if ( f != i ) {
00269                             t1 = m_prXVertex[v].GetFaceRing()[f];
00270                             m_prXVertex[v].GetFaceRing()[f] = m_prXVertex[v].GetFaceRing()[i];
00271                             m_prXVertex[v].GetFaceRing()[i] = t1;
00272                             t1 = vertexAt[f];
00273                             vertexAt[f] = vertexAt[i];
00274                             vertexAt[i] = t1;
00275                         }
00276 
00277                         // Use the fact that the vertices are listed CCW
00278                         for ( k = vertexAt[f]+1; k < face->GetNoVertices(); ++k ) {
00279                             if ( face->GetVertexNo(k) != v && face->GetVertexNo(k) != lastVertexNo ) {
00280                                 m_pviVertexRing1List[v].push_back( face->GetVertexNo(k) );
00281                             }
00282                         }
00283                         for ( k = 0; k < vertexAt[f]; ++k ) {
00284                             if ( face->GetVertexNo(k) != v && face->GetVertexNo(k) != lastVertexNo ) {
00285                                 m_pviVertexRing1List[v].push_back( face->GetVertexNo(k) );
00286                             }
00287                         }
00288                         lastVertexNo  = ( vertexAt[f]-1 < 0 
00289                                         ? face->GetVertexNo( face->GetNoVertices()-1 ) 
00290                                         : face->GetVertexNo( vertexAt[f]-1 ) );
00291                         break;
00292                     }
00293                 }
00294                 ++i;
00295             }
00296         }
00297         m_pviVertexRing1List[v].pop_back();
00298         //------------------------------------------------------------
00299     }
00300 }
00301 
00302 //******************************************************************************
00303 // ApplyAndResetTransform
00304 //******************************************************************************
00305 //-----------------------------------------------------------------------------
00306 template <typename T>
00307 void XPolygonalModel<T>::ApplyAndResetTransform ()
00308 {
00309     for ( int i = 0; i < m_iNoVertices; ++i ) {
00310         m_prXVertex[i].SetPosition( 
00311             (     GetTransform().RefToMatrixTransform() 
00312                 * Vector4<T>( m_prXVertex[i].GetPosition() )
00313             ).GetVector3()
00314         );
00315     }
00316 
00317 
00318     /*
00319     int i;
00320     //--------------------------------------------------------------------
00321     Vector3<T> Center = GetTransform().GetTranslation();
00322     if ( Center[0] != Math<T>::ZERO ) {
00323         for ( i = 0; i < m_iNoVertices; ++i )
00324             m_prXVertex[i][0] += Center[0];
00325         GetTransform().SetTranslation( 0, Math<T>::ZERO );
00326     }
00327     if ( Center[1] != Math<T>::ZERO ) {
00328         for ( i = 0; i < m_iNoVertices; ++i )
00329             m_prXVertex[i][1] += Center[1];
00330         GetTransform().SetTranslation( 1, Math<T>::ZERO );
00331     }
00332     if ( Center[2] != Math<T>::ZERO ) {
00333         for ( i = 0; i < m_iNoVertices; ++i )
00334             m_prXVertex[i][2] += Center[2];
00335         GetTransform().SetTranslation( 2, Math<T>::ZERO );
00336     }
00337     //--------------------------------------------------------------------
00338     Vector3<T> Rotation = GetTransform().GetRotationAngles();
00339     if ( Rotation[0] != Math<T>::ZERO ) {
00340         T deg = static_cast<T>( Rotation[0] * Math<T>::PI / 180.0 );
00341         T c = Math<T>::Cos( deg );
00342         T s = Math<T>::Sin( deg );
00343         T tmpX;
00344         for ( i = 0; i < m_iNoVertices; ++i ) {
00345             tmpX = m_prXVertex[i][1]*c - m_prXVertex[i][2]*s;
00346             m_prXVertex[i][2] = m_prXVertex[i][1]*s + m_prXVertex[i][2]*c;
00347             m_prXVertex[i][1] = tmpX;
00348         }
00349         GetTransform().SetRotationAxisAngle( 0, Math<T>::ZERO );
00350     }
00351     if ( Rotation[1] != Math<T>::ZERO ) {
00352         T deg = static_cast<T>( Rotation[1] * Math<T>::PI / 180.0 );
00353         T c = Math<T>::Cos( deg );
00354         T s = Math<T>::Sin( deg );
00355         T tmpX;
00356         for ( i = 0; i < m_iNoVertices; ++i ) {
00357             tmpX = m_prXVertex[i][0]*c + m_prXVertex[i][2]*s;
00358             m_prXVertex[i][2] = -(m_prXVertex[i][0]*s) + m_prXVertex[i][2]*c;
00359             m_prXVertex[i][0] = tmpX;
00360         }
00361         GetTransform().SetRotationAxisAngle( 1, Math<T>::ZERO );
00362     }
00363     if ( Rotation[2] != Math<T>::ZERO ) {
00364         T deg = static_cast<T>( Rotation[2] * Math<T>::PI / 180.0 );
00365         T c = Math<T>::Cos( deg );
00366         T s = Math<T>::Sin( deg );
00367         T tmpX;
00368         for ( i = 0; i < m_iNoVertices; ++i ) {
00369             tmpX = m_prXVertex[i][0]*c - m_prXVertex[i][1]*s;
00370             m_prXVertex[i][1] = m_prXVertex[i][0]*s + m_prXVertex[i][1]*c;
00371             m_prXVertex[i][0] = tmpX;
00372         }
00373         GetTransform().SetRotationAxisAngle( 2, Math<T>::ZERO );
00374     }
00375     //--------------------------------------------------------------------
00376     Vector3<T> Scale = GetTransform().GetScale();
00377     for ( int d = 0; d < 3; ++d ) {
00378         if ( Scale[d] != Math<T>::ONE ) {
00379             for ( i = 0; i < m_iNoVertices; ++i )
00380                 m_prXVertex[i][d] *= Scale[d];
00381             GetTransform().SetScale( d, Math<T>::ONE );
00382         }
00383     }
00384     //--------------------------------------------------------------------
00385     //*/
00386 
00387     //--------------------------------------------------------------------
00388     // Set Transformation to Identity Matrix
00389     GetTransform().MakeIdentity();
00390     //--------------------------------------------------------------------
00391     // Recalculate Bounding Volume(s)
00392     CalBoundingAABB();
00393     CalBoundingEllipsoid();
00394     CalBoundingSphere();
00395 }
00396 //-----------------------------------------------------------------------------
00397 //******************************************************************************
00398 
00399 //******************************************************************************
00400 // Virtual Fns from Collision Detection from ColDetSupport class
00401 //******************************************************************************
00402 //-----------------------------------------------------------------------------
00403 template <typename T>
00404 void XPolygonalModel<T>::CalBoundingAABB ()
00405 {
00406     m_paBoundingAABB[0][0] = m_paBoundingAABB[1][0] = m_prXVertex[0][0];
00407     m_paBoundingAABB[0][1] = m_paBoundingAABB[1][1] = m_prXVertex[0][1];
00408     m_paBoundingAABB[0][2] = m_paBoundingAABB[1][2] = m_prXVertex[0][2];
00409     for ( int i = 1; i < m_iNoVertices; ++i )
00410     {
00411         // Find lowest x, y, and z
00412         if ( m_paBoundingAABB[0][0] > m_prXVertex[i][0] )
00413              m_paBoundingAABB[0][0] = m_prXVertex[i][0];
00414         if ( m_paBoundingAABB[0][1] > m_prXVertex[i][1] )
00415              m_paBoundingAABB[0][1] = m_prXVertex[i][1];
00416         if ( m_paBoundingAABB[0][2] > m_prXVertex[i][2] )
00417              m_paBoundingAABB[0][2] = m_prXVertex[i][2];
00418         // Find highest x, y, and z
00419         if ( m_paBoundingAABB[1][0] < m_prXVertex[i][0] )
00420              m_paBoundingAABB[1][0] = m_prXVertex[i][0];
00421         if ( m_paBoundingAABB[1][1] < m_prXVertex[i][1] )
00422              m_paBoundingAABB[1][1] = m_prXVertex[i][1];
00423         if ( m_paBoundingAABB[1][2] < m_prXVertex[i][2] )
00424              m_paBoundingAABB[1][2] = m_prXVertex[i][2];
00425     }
00426     // Find the bounding volume center
00427     m_pBoundingCenter[0] = ( m_paBoundingAABB[0][0] + m_paBoundingAABB[1][0] ) / 2.0;
00428     m_pBoundingCenter[1] = ( m_paBoundingAABB[0][1] + m_paBoundingAABB[1][1] ) / 2.0;
00429     m_pBoundingCenter[2] = ( m_paBoundingAABB[0][2] + m_paBoundingAABB[1][2] ) / 2.0;
00430 }
00431 //-----------------------------------------------------------------------------
00432 template <typename T>
00433 void XPolygonalModel<T>::CalBoundingEllipsoid ()
00434 {
00435     /*
00436     m_pBoundingCenter[0] = ( m_paBoundingAABB[0][0] + m_paBoundingAABB[1][0] ) / 2.0;
00437     m_pBoundingCenter[1] = ( m_paBoundingAABB[0][1] + m_paBoundingAABB[1][1] ) / 2.0;
00438     m_pBoundingCenter[2] = ( m_paBoundingAABB[0][2] + m_paBoundingAABB[1][2] ) / 2.0;
00439     m_pBoundingEllipsoid[0] = fabs( (m_paBoundingAABB[0][0] - m_paBoundingAABB[1][0])/2.0 );
00440     m_pBoundingEllipsoid[1] = fabs( (m_paBoundingAABB[0][1] - m_paBoundingAABB[1][1])/2.0 );
00441     m_pBoundingEllipsoid[2] = fabs( (m_paBoundingAABB[0][2] - m_paBoundingAABB[1][2])/2.0 );
00442     //*/
00443 
00444     /*
00445     T xLength = m_paBoundingAABB[0][0] - m_paBoundingAABB[1][0];
00446     T yLength = m_paBoundingAABB[0][1] - m_paBoundingAABB[1][1];
00447     T zLength = m_paBoundingAABB[0][2] - m_paBoundingAABB[1][2];
00448     xLength *= xLength;
00449     yLength *= yLength;
00450     zLength *= zLength;
00451     m_pBoundingEllipsoid[0] = sqrt( yLength + zLength ) / 2.0;
00452     m_pBoundingEllipsoid[1] = sqrt( zLength + xLength ) / 2.0;
00453     m_pBoundingEllipsoid[2] = sqrt( xLength + yLength ) / 2.0;
00454     //*/
00455 
00456     T x = m_paBoundingAABB[1][0] - m_pBoundingCenter[0];
00457     x *= x;
00458     T y = m_paBoundingAABB[1][1] - m_pBoundingCenter[1];
00459     y *= y;
00460     T z = m_paBoundingAABB[1][2] - m_pBoundingCenter[2];
00461     z *= z;
00462     m_pBoundingEllipsoid[1] = sqrt( y + z );
00463     m_pBoundingEllipsoid[2] = sqrt( z + x );
00464     m_pBoundingEllipsoid[0] = sqrt( x + y );
00465 }
00466 //-----------------------------------------------------------------------------
00467 template <typename T>
00468 void XPolygonalModel<T>::CalBoundingSphere ()
00469 {
00470     /*
00471     T xLength = m_paBoundingAABB[0][0] - m_paBoundingAABB[1][0];
00472     T yLength = m_paBoundingAABB[0][1] - m_paBoundingAABB[1][1];
00473     T zLength = m_paBoundingAABB[0][2] - m_paBoundingAABB[1][2];
00474     xLength *= xLength;
00475     yLength *= yLength;
00476     zLength *= zLength;
00477     m_pBoundingSphere = sqrt( xLength + yLength + zLength ) / 2.0;
00478     //*/
00479     T squaredLength;
00480     m_pBoundingSphere = 0;
00481     for ( int i = 0; i < m_iNoVertices; ++i ) {
00482         squaredLength = (m_prXVertex[i].GetPosition() - m_pBoundingCenter).SquaredLength();
00483         if ( squaredLength > m_pBoundingSphere )
00484             m_pBoundingSphere = squaredLength;
00485     }
00486     m_pBoundingSphere = sqrt( m_pBoundingSphere );
00487 }
00488 //-----------------------------------------------------------------------------
00489 //******************************************************************************
00490 
00491 //-----------------------------------------------------------------------------
00492 //=============================================================================
00493 END_NAMESPACE_TAPs__OpenGL
00494 //-----------------------------------------------------------------------------
00495 //345678901234567890123456789012345678901234567890123456789012345678901234567890
00496 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines