![]() |
TAPs 0.7.7.3
|
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----+----