TAPs 0.7.7.3
TAPsSpringHalfEdgeModel.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002 TAPsSpringHalfEdgeModel.cpp
00003 
00004 A Polygonal Model based on half-edge data structure.
00005 (See TAPsSpringHalfEdgeModel.hpp for details)
00006 
00007 SUKITTI PUNAK   (02/27/2006)
00008 UPDATE          (04/10/2006)
00009 ******************************************************************************/
00010 #include "TAPsSpringHalfEdgeModel.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 SpringHalfEdgeModel<T>::SpringHalfEdgeModel ()
00021     : HalfEdgeModel<T>(), 
00022       m_pviListVertexRing1( NULL ), 
00023       m_pviListConnectedVertex( NULL ), 
00024       m_pviListSpring( NULL ), 
00025       m_iRigidity( 1 ), 
00026       m_tPtMass( 1 ), 
00027       m_tKStiffness( 1 ), 
00028       m_tKDamper( 1 ) 
00029 {
00030     //----------------------------------------------------------------
00031     //std::cout << "Number of Vertex: " << GetNoVertices();
00032     //std::cout << "Number of Vertex: " << GetNoVertices();
00033     #ifdef  TAPs_ENABLE_DEBUG
00034     std::cout << "SpringHalfEdgeModel<" << typeid(T).name() << "> Constructor\n";
00035     #endif//TAPs_ENABLE_DEBUG
00036 }
00037 //-----------------------------------------------------------------------------
00038 // destructor
00039 template <typename T>
00040 SpringHalfEdgeModel<T>::~SpringHalfEdgeModel ()
00041 {
00042     DeleteAllData();
00043     //----------------------------------------------------------------
00044     // For simulation
00045     delete m_prODESolver;
00046     //----------------------------------------------------------------
00047     #ifdef  TAPs_ENABLE_DEBUG
00048     std::cout << "SpringHalfEdgeModel<" << typeid(T).name() << "> Destructor\n";
00049     #endif//TAPs_ENABLE_DEBUG
00050 }
00051 //-----------------------------------------------------------------------------
00052 // Initialize
00053 // a virtual fn from Model class
00054 template <typename T>
00055 void SpringHalfEdgeModel<T>::Initialize ()
00056 {
00057     HalfEdgeModel<T>::Initialize();
00058     //--------------------------------------------------------------------
00059     #ifdef  TAPs_ENABLE_DEBUG
00060     std::cout << "++++++++++++++Initialize HALF-EDGE SPRING MODEL++++++++++++++\n";
00061     #endif//TAPs_ENABLE_DEBUG
00062 }
00063 //-----------------------------------------------------------------------------
00064 // Create Mesh Springs
00065 template <typename T>
00066 void SpringHalfEdgeModel<T>::CreateMeshSprings ( 
00067             int rigidity, T mass, T Ks, T Kd )
00068 {
00069     PrepareData();
00070     //--------------------------------------------------------------------
00071     // For Simulation
00072     if ( ( m_prODESolver = new Simulation::ODESolverEuler<T>() ) == NULL ) {
00073     //if ( ( m_prODESolver = new Simulation::ODESolverMidpoint<T>() ) == NULL ) {
00074     //if ( ( m_prODESolver = new Simulation::ODESolverRungeKutta4<T>() ) == NULL ) {
00075         #ifdef TAPs_ENABLE_DEBUG
00076         std::cerr   << "ERROR => SpringHalfEdgeModel Constructor:" 
00077                     << " Cannot allocate memory for an ODE solver!" 
00078                     << std::endl;
00079         #endif
00080         delete this;
00081         return;
00082     }
00083     //--------------------------------------------------------------------
00084     m_iStateSize = static_cast<int>( m_vpParticleRef.size() );
00085     m_prODESolver->SetSize( m_iStateSize * 6 );
00086     x0   = &xData_1;
00087     xEnd = &xData_2;
00088     x0->resize(   m_iStateSize * 6 );
00089     xEnd->resize( m_iStateSize * 6 );
00090     StateToArray( &(*xEnd)[0] );
00091     //--------------------------------------------------------------------
00092     #ifdef  TAPs_ENABLE_DEBUG
00093     std::cout << "++++++++++++++HALF-EDGE SPRING MODEL++++++++++++++\n";
00094     std::cout << "++++++++++++++ --> m_iStateSize = " << m_iStateSize << "\n";
00095     std::cout << "++++++++++++++HALF-EDGE SPRING MODEL++++++++++++++\n";
00096     #endif//TAPs_ENABLE_DEBUG
00097     //--------------------------------------------------------------------
00098     SetListOf1RingVertices();
00099     SetMassOfParticles( mass );
00100     CreateSprings( Ks, Kd, rigidity );  // A recursive method for creating springs
00101 
00102     #ifdef  TAPs_ENABLE_DEBUG
00103     std::cout << "Spring Mesh Rigidity: " << m_iRigidity << "\n";
00104     std::cout << "The Total Number of Springs is " << static_cast<int>(m_vpSpringRef.size()) << "\n";
00105     #endif//TAPs_ENABLE_DEBUG
00106 
00107     /*
00108     //--------------------------------------------------------------------
00109     // DEBUG PRINTOUT
00110     for ( int i = 0; i < static_cast<int>( m_vpParticleRef.size() ); ++i ) {
00111         std::cout << *m_vpParticleRef[i] << "\n";
00112     }
00113     for ( int i = 0; i < static_cast<int>( m_vpSpringRef.size() ); ++i ) {
00114         std::cout << *m_vpSpringRef[i] << "\n";
00115     }
00116     //*/
00117 
00118     //--------------------------------------------------------------------
00119     /*
00120     for ( int i = 0; i < GetNoVertices(); ++i ) {
00121         std::cout << "Vertex#" << i << ":";
00122         for ( int j = 0; j < static_cast<int>(m_pviListConnectedVertex[i].size()); ++j ) {
00123             std::cout << " " << m_pviListConnectedVertex[i][j];
00124         }
00125         std::cout << "\n";
00126     }
00127     //*/
00128 }
00129 //-----------------------------------------------------------------------------
00130 //******************************************************************************
00131 
00132 //******************************************************************************
00133 // Helper Fn(s)
00134 //-----------------------------------------------------------------------------
00135 template <typename T>
00136 void SpringHalfEdgeModel<T>::ChangeConstantStiffnessOfAllSprings ( T val )
00137 {
00138     std::vector< SpringRef<T> * >::iterator pos;
00139     for ( pos = m_vpSpringRef.begin(); pos < m_vpSpringRef.end(); ++pos ) {
00140         (*pos)->SetConstantK( val );
00141     }
00142 }
00143 //-----------------------------------------------------------------------------
00144 template <typename T>
00145 void SpringHalfEdgeModel<T>::ChangeConstantDampingOfAllSprings ( T val )
00146 {
00147     std::vector< SpringRef<T> * >::iterator pos;
00148     for ( pos = m_vpSpringRef.begin(); pos < m_vpSpringRef.end(); ++pos ) {
00149         (*pos)->SetDampingD( val );
00150     }
00151 }
00152 //-----------------------------------------------------------------------------
00153 template <typename T>
00154 void SpringHalfEdgeModel<T>::ChangeMassOfAllPoints ( T val )
00155 {
00156     std::vector< ParticleRef<T> * >::iterator pos;
00157     for ( pos = m_vpParticleRef.begin(); pos < m_vpParticleRef.end(); ++pos ) {
00158         (*pos)->SetMass( val );
00159     }
00160 }
00161 //-----------------------------------------------------------------------------
00162 //******************************************************************************
00163 
00164 //******************************************************************************
00165 // Helper Fn(s)
00166 //-----------------------------------------------------------------------------
00167 template <typename T>
00168 void SpringHalfEdgeModel<T>::DeleteAllData ()
00169 {
00170     //m_ptrHEVertex.clear();
00171     delete [] m_pviListVertexRing1;
00172     delete [] m_pviListConnectedVertex;
00173     delete [] m_pviListSpring;
00174     //m_listParticleRef.clear();
00175     //m_listSpringRef.clear();
00176     //m_ptrSpringRef.clear();
00177     for ( int i = 0; i < static_cast<int>( m_vpParticleRef.size() ); ++i ) {
00178         delete m_vpParticleRef[i];
00179     }
00180     for ( int i = 0; i < static_cast<int>( m_vpSpringRef.size() ); ++i ) {
00181         delete m_vpSpringRef[i];
00182     }
00183 }
00184 //-----------------------------------------------------------------------------
00185 template <typename T>
00186 void SpringHalfEdgeModel<T>::SetListOf1RingVertices ()
00187 {
00188     HEHalfEdge<T> * firstHalfEdge, * currentHalfEdge;
00189     HEVertex<T> *   heVertex = GetVertexList()->Head();
00190     HEVertex<T> *   currentVertex;
00191 
00192     #ifdef  TAPs_ENABLE_DEBUG
00193     std::cout << "Progress: ";
00194     #endif//TAPs_ENABLE_DEBUG
00195 
00196     #ifdef  TAPs_ENABLE_DEBUG
00197     int count = 0;
00198     #endif//TAPs_ENABLE_DEBUG
00199 
00200     int size = static_cast<int>( m_vpHEVertex.size() );
00201     for ( int v = 0; v < size; ++v ) {
00202 
00203         #ifdef  TAPs_ENABLE_DEBUG
00204         if ( ++count % 100 == 0 )   std::cout << ".";
00205         #endif//TAPs_ENABLE_DEBUG
00206 
00207         currentHalfEdge = firstHalfEdge = heVertex->IncidentHalfEdge();
00208         do {
00209             currentVertex = currentHalfEdge->Pair()->Vertex();
00210             for ( int i = 0; i < size; ++i ) {
00211                 if ( currentVertex == m_vpHEVertex[i] ) {
00212                     m_pviListVertexRing1[v].push_back( i );
00213                     break;
00214                 }
00215             }
00216             currentHalfEdge = currentHalfEdge->Pair()->Next();
00217         } while ( firstHalfEdge != currentHalfEdge );
00218         heVertex = heVertex->Next();
00219 
00221         //std::cout << "One Ring Size " 
00222         //  << static_cast<int>( m_pviListVertexRing1[v].size() ) << ":";
00223         //for ( int i = 0; i < static_cast<int>( m_pviListVertexRing1[v].size() ); ++i ) {
00224         //  std::cout << " " << m_pviListVertexRing1[v][i];
00225         //}
00226         //std::cout << "\n";
00227     }
00228 
00229     #ifdef  TAPs_ENABLE_DEBUG
00230     std::cout << " Done\n";
00231     #endif//TAPs_ENABLE_DEBUG
00232 }
00233 //-----------------------------------------------------------------------------
00234 template <typename T>
00235 void SpringHalfEdgeModel<T>::PrepareData ()
00236 {
00237     int size = GetVertexList()->Size();
00238     if ( m_pviListVertexRing1 )     delete [] m_pviListVertexRing1;
00239     if ( m_pviListConnectedVertex ) delete [] m_pviListConnectedVertex;
00240     if ( m_pviListSpring )          delete [] m_pviListSpring;
00241     m_pviListVertexRing1     = new std::vector<int>[ size ];
00242     m_pviListConnectedVertex = new std::vector<int>[ size ];
00243     m_pviListSpring          = new std::vector<int>[ size ];
00244     //-----------------------------------------------------------------------
00245     // Setup pointers to HEVertex
00246     HEVertex<T> * heVertex = GetVertexList()->Head();
00247     while ( heVertex ) {
00248         m_vpHEVertex.push_back( heVertex );
00249         m_vpParticleRef.push_back( new ParticleRef<T>( heVertex->GetProtectedPosition() ) );
00250         //m_vpParticleRef.push_back( new ParticleRef<T>( const_cast< Vector3<T> & >( heVertex->GetPosition() ) ) );
00251         heVertex = heVertex->Next();
00252     }
00253 }
00254 //-----------------------------------------------------------------------------
00255 template <typename T>
00256 void SpringHalfEdgeModel<T>::SetMassOfParticles ( T mass )
00257 {
00258     //std::list< ParticleRef<T> >::iterator pos;
00259     //for ( pos = m_listParticleRef.begin(); pos != m_listParticleRef.end(); ++pos ) {
00260     //  pos->SetMass( mass );
00261     //}
00262     for ( int i = 0; i < static_cast<int>( m_vpParticleRef.size() ); ++i ) {
00263         m_vpParticleRef[i]->SetMass( mass );
00264     }
00265 }
00266 //-----------------------------------------------------------------------------
00267 template <typename T>
00268 bool SpringHalfEdgeModel<T>::CheckASpringExistance ( int p1, int p2 )
00269 {
00270     int size = static_cast<int>( m_pviListConnectedVertex[p1].size() );
00271     for ( int i = 0; i < size; ++i ) {
00272         if ( m_pviListConnectedVertex[p1][i] == p2 )    return true;
00273     }
00274     return false;
00275 }
00276 //-----------------------------------------------------------------------------
00277 template <typename T>
00278 void SpringHalfEdgeModel<T>::CreateASpring ( 
00279                 T Ks, T Kd, int p1, int p2, int hops )
00280 {
00281     int pos = static_cast<int>( m_vpSpringRef.size() );
00282     m_vpSpringRef.push_back( 
00283         new SpringRef<T>( 
00284                 *(m_vpParticleRef[p1]), 
00285                 *(m_vpParticleRef[p2]), 
00286                 Ks, Kd, 
00287                 hops ) );
00288     m_pviListConnectedVertex[p1].push_back( p2 );
00289     m_pviListConnectedVertex[p2].push_back( p1 );
00290     m_pviListSpring[p1].push_back( pos );
00291     m_pviListSpring[p2].push_back( pos );
00292     //std::cout << "# of Hops: " << hops << "\n";
00293     //std::cout << "Create Spring with " << hops << " hop(s)\n";
00294 }
00295 //-----------------------------------------------------------------------------
00296 template <typename T>
00297 void SpringHalfEdgeModel<T>::CreateSprings ( T Ks, T Kd, int rigidity )
00298 {
00299     m_iRigidity = rigidity;
00300     int size = static_cast<int>( m_vpParticleRef.size() );
00301     bool * isMark = new bool[size];
00302     for ( int i = 0; i < size; ++i ) {
00303         isMark[i] = false;
00304     }
00305     //--------------------------------------------------------------------
00306     for ( int i = 0; i < size; ++i ) {
00307         std::vector<int> particleSet;       // start as empty set
00308         //std::cout << static_cast<int>(particleSet.size()) << "\n";
00309         BFSCreateSprings(   Ks, Kd, 0, 
00310                             i, i,           // particle#1, particle#2
00311                             particleSet, 
00312                             isMark );
00313         for ( int j = 0; j < static_cast<int>( particleSet.size() ); ++j ) {
00314             isMark[ particleSet[j] ] = false;
00315         }
00316     }
00317 }
00318 //-----------------------------------------------------------------------------
00319 template <typename T>
00320 void SpringHalfEdgeModel<T>::BFSCreateSprings ( 
00321                 T Ks, T Kd, int rigidity,       // Ks, Kd, & hop distance
00322                 int p1, int p2,                 // particle#1 & #2
00323                 std::vector<int> & particleSet, // set of connected particles
00324                 bool * isMark )                 // marked particles in particleSet
00325 {
00326     if ( rigidity >= m_iRigidity ) return;
00327     //--------------------------------------------------------------------
00328     // Keep the particle reference in particleSet
00329     // And mark it as visited
00330     particleSet.push_back( p2 );
00331     isMark[ p2 ] = true;
00332     //--------------------------------------------------------------------
00333     // Traverse each edge of p1
00334     ++rigidity;
00335     int p3;
00336     for ( int i = 0; i < static_cast<int>( m_pviListVertexRing1[p2].size() ); ++i ) {
00337         p3 = m_pviListVertexRing1[p2][i];
00338         if ( !isMark[ p3 ] ) {
00339             if ( !CheckASpringExistance( p1, p3 ) ) {
00340                 CreateASpring( Ks, Kd, p1, p3, rigidity );
00341             }
00342         }
00343     }
00344     // This makes it become Breadth First Search
00345     for ( int i = 0; i < static_cast<int>( m_pviListVertexRing1[p2].size() ); ++i ) {
00346         p3 = m_pviListVertexRing1[p2][i];
00347         BFSCreateSprings( Ks, Kd, rigidity, p1, p3, particleSet, isMark );
00348     }
00349     //--------------------------------------------------------------------
00350 }
00351 /*
00352 //-----------------------------------------------------------------------------
00353 template <typename T>
00354 void SpringHalfEdgeModel<T>::DFSCreateSprings ( 
00355                 T Ks, T Kd, int rigidity,       // Ks, Kd, & hop distance
00356                 int p1, int p2,                 // particle#1 & #2
00357                 std::vector<int> & particleSet, // set of connected particles
00358                 bool * isMark )                 // marked particles in particleSet
00359 {
00360     if ( rigidity >= m_iRigidity ) return;
00361     //--------------------------------------------------------------------
00362     // Keep the particle reference in particleSet
00363     // And mark it as visited
00364     particleSet.push_back( p2 );
00365     isMark[ p2 ] = true;
00366     //--------------------------------------------------------------------
00367     // Traverse each edge of p1
00368     ++rigidity;
00369     int p3;
00370     for ( int i = 0; i < static_cast<int>( m_pviListVertexRing1[p2].size() ); ++i ) {
00371         p3 = m_pviListVertexRing1[p2][i];
00372         if ( !isMark[ p3 ] ) {
00373             if ( !CheckASpringExistance( p1, p3 ) ) {
00374                 CreateASpring( Ks, Kd, p1, p3, rigidity );
00375             }
00376             DFSCreateSprings( Ks, Kd, rigidity, p1, p3, particleSet, isMark );
00377         }
00378     }
00379     //--------------------------------------------------------------------
00380 }
00381 //*/
00382 //-----------------------------------------------------------------------------
00383 //******************************************************************************
00384 
00385 
00386 //=============================================================================
00387 // For Simulation
00388 //-----------------------------------------------------------------------------
00389 // Advance Simulation
00390 template <typename T>
00391 void SpringHalfEdgeModel<T>::AdvanceSimulation ( T tCurrent, T tNext )
00392 {
00393     //-----------------------------------------------------
00394     // Swap pointers
00395     Simulation::VectorSet<T> * tmpPtr = x0;
00396     x0   = xEnd;
00397     xEnd = tmpPtr;
00398     //------------------------------------------------------
00399     // ODE Solver
00400     m_prODESolver->Solve( *x0, *xEnd, tCurrent, tNext, DxDt, this );
00401     //------------------------------------------------------
00402     // Copy d/dt X(tNext) into state variables xEnd
00403     ArrayToState( &(*xEnd)[0] );
00404     //------------------------------------------------------
00405     //SimGravity( tCurrent, tNext );
00406     //------------------------------------------------------
00407     GetBVHTree()->Update();
00408 
00409     CalAndSetNormals();
00410 }
00411 //-----------------------------------------------------------------------------
00412 // Advance Simulation
00413 template <typename T>
00414 void SpringHalfEdgeModel<T>::AdvanceSimulation ( Simulation::SimClock<T> & simClock )
00415 {
00416     std::cout << "SpringHalfEdgeModel<T>::AdvanceSimulation ( Simulation::SimClock<T> & simClock ) -- NOT IMPLEMENTED YET!!!\n";
00417 }
00418 //-----------------------------------------------------------------------------
00419 // DxDt
00420 template <typename T>
00421 bool SpringHalfEdgeModel<T>::DxDt ( 
00422     T                       dt,         // I/P: time step
00423     Simulation::VectorSet<T> &  x,      // I/p: array  x = {pos, vel}
00424     Simulation::VectorSet<T> &  xdot,   // O/P: array xdot = {vel, accel}
00425     void *                  userData    // O/P: array of user data
00426 )
00427 {   
00428     //------------------------------------------------------
00429     // Convert userData ptr to ModelStrand ptr
00430     SpringHalfEdgeModel<T> *pThis = static_cast<SpringHalfEdgeModel<T> *>( userData );
00431     assert( pThis );
00432     pThis->ClearAllForces();
00433     //------------------------------------------------------
00434     for ( int i = 0; i < static_cast<int>( pThis->m_vpSpringRef.size() ); ++i ) {
00435         pThis->m_vpSpringRef[i]->CalAndSetForce();
00436     }
00437     //------------------------------------------------------
00438     pThis->DdtStateToArray( &xdot[0], dt );
00439     //------------------------------------------------------
00440     return true;
00441 }
00442 //-----------------------------------------------------------------------------
00443 // StateToArray
00444 template <typename T>
00445 void SpringHalfEdgeModel<T>::StateToArray ( T *dst )
00446 {
00447     for ( int i = 0; i < m_iStateSize; ++i ) {
00448         *(dst++) = m_vpParticleRef[i]->GetPosition()[0];
00449         *(dst++) = m_vpParticleRef[i]->GetPosition()[1];
00450         *(dst++) = m_vpParticleRef[i]->GetPosition()[2];
00451         *(dst++) = m_vpParticleRef[i]->GetVelocity()[0];
00452         *(dst++) = m_vpParticleRef[i]->GetVelocity()[1];
00453         *(dst++) = m_vpParticleRef[i]->GetVelocity()[2];
00454     }
00455 }
00456 //-----------------------------------------------------------------------------
00457 // ArrayToState
00458 template <typename T>
00459 void SpringHalfEdgeModel<T>::ArrayToState ( T *src )
00460 {
00461     for ( int i = 0; i < m_iStateSize; ++i ) {
00462         m_vpParticleRef[i]->SetPosition( *src, *(src+1), *(src+2) );
00463         src += 3;
00464         m_vpParticleRef[i]->SetVelocity( *src, *(src+1), *(src+2) );
00465         src += 3;
00466     }
00467 }
00468 //-----------------------------------------------------------------------------
00469 // DdtStateToArray
00470 template <typename T>
00471 void SpringHalfEdgeModel<T>::DdtStateToArray ( T *xdot, T dt )
00472 {
00473     for ( int i = 0; i < m_iStateSize; ++i ) {
00474         if ( m_vpParticleRef[i]->GetFixStatus() ) {
00475             *(xdot++) = 
00476             *(xdot++) = 
00477             *(xdot++) = 
00478             *(xdot++) = 
00479             *(xdot++) = 
00480             *(xdot++) = 0;
00481         }
00482         else {
00483             //m_prForce[i] = m_StructForce[i].gravity;
00484             //m_prVelocity[i][1] = m_prForce[i][1] * m_prVertex[i][1] * dt;
00485             //----------------------------------------
00486             *(xdot++) = m_vpParticleRef[i]->GetVelocity()[0];
00487             *(xdot++) = m_vpParticleRef[i]->GetVelocity()[1];
00488             *(xdot++) = m_vpParticleRef[i]->GetVelocity()[2];
00489             *(xdot++) = m_vpParticleRef[i]->GetForce()[0];
00490             *(xdot++) = m_vpParticleRef[i]->GetForce()[1];
00491             *(xdot++) = m_vpParticleRef[i]->GetForce()[2];
00492         }
00493     }
00494 }
00495 //-----------------------------------------------------------------------------
00496 // ClearForces
00497 template <typename T>
00498 void SpringHalfEdgeModel<T>::ClearAllForces ()
00499 {
00500     for ( int i = 0; i < static_cast<int>( m_vpParticleRef.size() ); ++i ) {
00501         m_vpParticleRef[i]->SetForce( 0, 0, 0 );
00502     }
00503 }
00504 //-----------------------------------------------------------------------------
00505 //=============================================================================
00506 
00507 
00508 //-----------------------------------------------------------------------------
00509 //=============================================================================
00510 END_NAMESPACE_TAPs__OpenGL
00511 //-----------------------------------------------------------------------------
00512 //34567890123456789012345678901234567890123456789012345678901234567890123456789
00513 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines