![]() |
TAPs 0.7.7.3
|
00001 /****************************************************************************** 00002 TAPsModelStrand.cpp 00003 ******************************************************************************/ 00007 /****************************************************************************** 00008 SUKITTI PUNAK (07/10/2005) 00009 UPDATE (09/03/2010) 00010 ******************************************************************************/ 00011 #include "TAPsModelStrand.hpp" 00012 // Using Inclusion Model (i.e. definitions are included in declarations) 00013 // (this name.cpp is included in name.hpp) 00014 // Each friend is defined directly inside its declaration. 00015 00016 BEGIN_NAMESPACE_TAPs__OpenGL 00017 //============================================================================= 00018 #ifdef TAPs_ADVANCED_SIMULATION 00019 template <typename T> unsigned int ModelStrand<T>::TotalModels = 0; 00020 #endif//TAPs_ADVANCED_SIMULATION 00021 //----------------------------------------------------------------------------- 00022 // For Assisting Constructor(s) 00023 template <typename T> 00024 void ModelStrand<T>::AllocateLinkProps ( Vector3<T> &posOfVertex0 ) 00025 { 00026 //---------------------------------------------------------------- 00027 // Create the the link direction (from 0 to # of vertices-1) 00028 if ( ( m_prLinkDirection = new Vector3<T>[ m_iNoLinks ] ) == NULL ) { 00029 #ifdef TAPs_ENABLE_DEBUG 00030 std::cerr << "ERROR => ModelStrand Constructor:" 00031 << " Cannot allocate memory for strand links!" 00032 << std::endl; 00033 #endif 00034 delete this; 00035 return; 00036 } 00037 00038 #ifdef TAPs_USE_EXTERNAL_ODE_SOLVER 00039 //---------------------------------------------------------------- 00040 // Create Links 00041 if ( ( m_prVertex = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00042 #ifdef TAPs_ENABLE_DEBUG 00043 std::cerr << "ERROR => ModelStrand Constructor:" 00044 << " Cannot allocate memory for strand links!" 00045 << std::endl; 00046 #endif 00047 delete this; 00048 return; 00049 } 00050 //---------------------------------------------------------------- 00051 // Create Velocities 00052 if ( ( m_prVelocity = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00053 #ifdef TAPs_ENABLE_DEBUG 00054 std::cerr << "ERROR => ModelStrand Constructor:" 00055 << " Cannot allocate memory for strand velocities!" 00056 << std::endl; 00057 #endif 00058 delete this; 00059 return; 00060 } 00061 //---------------------------------------------------------------- 00062 // Create Forces 00063 if ( ( m_prForce = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00064 #ifdef TAPs_ENABLE_DEBUG 00065 std::cerr << "ERROR => ModelStrand Constructor:" 00066 << " Cannot allocate memory for strand forces!" 00067 << std::endl; 00068 #endif 00069 delete this; 00070 return; 00071 } 00072 00073 #else //TAPs_USE_EXTERNAL_ODE_SOLVER 00074 00075 //---------------------------------------------------------------- 00076 // Prepare counters 00077 00078 // For Euler Integration 00079 #ifdef TAPs_USE_INTERNAL_ODE_SOLVER_EULER 00080 int numPositionSets = 2; 00081 int numVelocitySets = 2; 00082 int numForceSets = 2; 00083 m_PositionCounter.SetValueHighest( numPositionSets ); 00084 m_VelocityCounter.SetValueHighest( numVelocitySets ); 00085 m_ForceCounter.SetValueHighest( numForceSets ); 00086 #endif//TAPs_USE_INTERNAL_ODE_SOLVER_EULER 00087 00088 //---------------------------------------------------------------- 00089 00090 //---------------------------------------------------------------- 00091 // Create Links 00092 if ( ( m_prVertexPositionRecord = new Vector3<T>*[numPositionSets] ) == NULL ) { 00093 #ifdef TAPs_ENABLE_DEBUG 00094 std::cerr << "ERROR => ModelStrand Constructor:" 00095 << " Cannot allocate memory for strand links!" 00096 << std::endl; 00097 #endif 00098 delete this; 00099 return; 00100 } 00101 for ( int i = 0; i < numPositionSets; ++i ) { 00102 if ( ( m_prVertexPositionRecord[i] = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00103 #ifdef TAPs_ENABLE_DEBUG 00104 std::cerr << "ERROR => ModelStrand Constructor:" 00105 << " Cannot allocate memory for strand links!" 00106 << std::endl; 00107 #endif 00108 delete this; 00109 return; 00110 } 00111 } 00112 m_prVertex = m_prVertexPositionRecord[0]; 00113 m_prVertexPrev = m_prVertex; 00114 //---------------------------------------------------------------- 00115 // Create Velocities 00116 if ( ( m_prVertexVelocityRecord = new Vector3<T>*[numVelocitySets] ) == NULL ) { 00117 #ifdef TAPs_ENABLE_DEBUG 00118 std::cerr << "ERROR => ModelStrand Constructor:" 00119 << " Cannot allocate memory for strand velocitys!" 00120 << std::endl; 00121 #endif 00122 delete this; 00123 return; 00124 } 00125 for ( int i = 0; i < numVelocitySets; ++i ) { 00126 if ( ( m_prVertexVelocityRecord[i] = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00127 #ifdef TAPs_ENABLE_DEBUG 00128 std::cerr << "ERROR => ModelStrand Constructor:" 00129 << " Cannot allocate memory for strand velocitys!" 00130 << std::endl; 00131 #endif 00132 delete this; 00133 return; 00134 } 00135 } 00136 m_prVelocity = m_prVertexVelocityRecord[0]; 00137 m_prVelocityPrev = m_prVelocity; 00138 //---------------------------------------------------------------- 00139 // Create Forces 00140 if ( ( m_prVertexForceRecord = new Vector3<T>*[numForceSets] ) == NULL ) { 00141 #ifdef TAPs_ENABLE_DEBUG 00142 std::cerr << "ERROR => ModelStrand Constructor:" 00143 << " Cannot allocate memory for strand forces!" 00144 << std::endl; 00145 #endif 00146 delete this; 00147 return; 00148 } 00149 for ( int i = 0; i < numForceSets; ++i ) { 00150 if ( ( m_prVertexForceRecord[i] = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00151 #ifdef TAPs_ENABLE_DEBUG 00152 std::cerr << "ERROR => ModelStrand Constructor:" 00153 << " Cannot allocate memory for strand forces!" 00154 << std::endl; 00155 #endif 00156 delete this; 00157 return; 00158 } 00159 } 00160 m_prForce = m_prVertexForceRecord[0]; 00161 m_prForcePrev = m_prForce; 00162 //---------------------------------------------------------------- 00163 00164 #endif//TAPs_USE_EXTERNAL_ODE_SOLVER 00165 00166 //---------------------------------------------------------------- 00167 // Setup the start shape of the strand 00168 SetupShape ( posOfVertex0 ); 00169 /* 00170 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00171 posOfVertex0[0] += m_tLinkLength; 00172 m_prVertex[i] = posOfVertex0; 00173 } 00174 //*/ 00175 //---------------------------------------------------------------- 00176 // Create Links 00177 if ( ( m_prOrigVertex = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00178 #ifdef TAPs_ENABLE_DEBUG 00179 std::cerr << "ERROR => ModelStrand Constructor:" 00180 << " Cannot allocate memory for strand links!" 00181 << std::endl; 00182 #endif 00183 delete this; 00184 return; 00185 } 00186 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00187 m_prOrigVertex[i] = m_prVertex[i]; 00188 } 00189 //---------------------------------------------------------------- 00190 // Create Prev Links 00191 if ( ( m_prVertexPrevPos = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00192 #ifdef TAPs_ENABLE_DEBUG 00193 std::cerr << "ERROR => ModelStrand Constructor:" 00194 << " Cannot allocate memory for strand links!" 00195 << std::endl; 00196 #endif 00197 delete this; 00198 return; 00199 } 00200 //---------------------------------------------------------------- 00201 // Create Temp Vertices Set 1 00202 if ( ( m_prTempVertex1 = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00203 #ifdef TAPs_ENABLE_DEBUG 00204 std::cerr << "ERROR => ModelStrand Constructor:" 00205 << " Cannot allocate memory for strand links (temp set 1)!" 00206 << std::endl; 00207 #endif 00208 delete this; 00209 return; 00210 } 00211 //---------------------------------------------------------------- 00212 // Create Temp Vertices Set 2 00213 if ( ( m_prTempVertex2 = new Vector3<T>[ m_iNoLinks + 1 ] ) == NULL ) { 00214 #ifdef TAPs_ENABLE_DEBUG 00215 std::cerr << "ERROR => ModelStrand Constructor:" 00216 << " Cannot allocate memory for strand links (temp set 1)!" 00217 << std::endl; 00218 #endif 00219 delete this; 00220 return; 00221 } 00222 //---------------------------------------------------------------- 00223 // Create Rotations 00224 if ( ( m_prDegRot = new T[ m_iNoLinks + 1 ] ) == NULL ) { 00225 #ifdef TAPs_ENABLE_DEBUG 00226 std::cerr << "ERROR => ModelStrand Constructor:" 00227 << " Cannot allocate memory for strand rotations!" 00228 << std::endl; 00229 #endif 00230 delete this; 00231 return; 00232 } 00233 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00234 m_prDegRot[i] = T(); 00235 } 00236 //---------------------------------------------------------------- 00237 // Create Fix Status Flags 00238 if ( ( m_prIsFixed = new bool[ m_iNoLinks + 1 ] ) == NULL ) { 00239 #ifdef TAPs_ENABLE_DEBUG 00240 std::cerr << "ERROR => ModelStrand Constructor:" 00241 << " Cannot allocate memory for strand fix flags!" 00242 << std::endl; 00243 #endif 00244 delete this; 00245 return; 00246 } 00247 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00248 m_prIsFixed[i] = false; 00249 } 00250 00251 /* 00252 //---------------------------------------------------------------- 00253 // Create Was Intersect Status Flags 00254 if ( ( m_prWasIntersect = new char[ m_iNoLinks ] ) == NULL ) { 00255 #ifdef TAPs_ENABLE_DEBUG 00256 std::cerr << "ERROR => ModelStrand Constructor:" 00257 << " Cannot allocate memory for strand 'was intersect' flags!" 00258 << std::endl; 00259 #endif 00260 delete this; 00261 return; 00262 } 00263 for ( int i = 0; i < m_iNoLinks; ++i ) { 00264 m_prWasIntersect[i] = 0; 00265 } 00266 //*/ 00267 00268 //---------------------------------------------------------------- 00269 // Create (Subdivision) links 00270 if ( ( m_prDispVertex = new Vector3<T>[ m_iNoLinks * 2 ] ) == NULL ) { 00271 #ifdef TAPs_ENABLE_DEBUG 00272 std::cerr << "ERROR => ModelStrand Constructor:" 00273 << " Cannot allocate memory for strand (display) links!" 00274 << std::endl; 00275 #endif 00276 delete this; 00277 return; 00278 } 00279 SetDisplayLinks(); 00280 //---------------------------------------------------------------- 00281 // Create Structure Forces 00282 if ( ( m_StructForce = new StructForce[ m_iNoLinks + 1 ] ) == NULL ) { 00283 #ifdef TAPs_ENABLE_DEBUG 00284 std::cerr << "ERROR => ModelStrand Constructor:" 00285 << " Cannot allocate memory for strand forces!" 00286 << std::endl; 00287 #endif 00288 delete this; 00289 return; 00290 } 00291 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00292 m_StructForce[i].gravity = Vector3<T>( 0, -Physics_SI::K::g*m_tPointWeight, 0 ); 00293 //m_StructForce[i].antiBending; 00294 } 00295 //---------------------------------------------------------------- 00296 // For simulation 00297 #ifdef TAPs_USE_EXTERNAL_ODE_SOLVER 00298 if ( ( m_prODESolver = new Simulation::ODESolverEuler<T>() ) == NULL ) { 00299 //if ( ( m_prODESolver = new Simulation::ODESolverMidpoint<T>() ) == NULL ) { 00300 //if ( ( m_prODESolver = new Simulation::ODESolverRungeKutta4<T>() ) == NULL ) { 00301 #ifdef TAPs_ENABLE_DEBUG 00302 std::cerr << "ERROR => ModelStrand Constructor:" 00303 << " Cannot allocate memory for strand ODE solver!" 00304 << std::endl; 00305 #endif 00306 delete this; 00307 return; 00308 } 00309 m_iStateSize = (m_iNoLinks + 1) * 6; 00310 m_prODESolver->SetSize( m_iStateSize ); 00311 x0.resize( m_iStateSize ); 00312 xEnd.resize( m_iStateSize ); 00313 StateToArray( &xEnd[0] ); 00314 #endif//TAPs_USE_EXTERNAL_ODE_SOLVER 00315 00316 //---------------------------------------------------------------- 00317 InitCurrentShape(); 00318 00319 // Save Previous Positions for roll back position 00320 SavePreviousPositions(); 00321 00322 BuildBVHTree(); 00323 CheckSelfIntersections(); 00324 00325 #ifdef TAPs_DEBUG_MODE 00326 std::cout << "Sphere Bounding Hierarchy for Strand with " 00327 << m_BVHTree->CountNodes() << " nodes" 00328 << " which " << m_BVHTree->CountLeafNodes() 00329 << " of them are leaf nodes." << "\n"; 00330 #endif//TAPs_DEBUG_MODE 00331 //---------------------------------------------------------------- 00332 00333 //=============================================================== 00334 #ifdef TAPs_STRAND_LOCK_SEGMENTS 00335 //--------------------------------------------------------------- 00336 // Initialization for lock segments 00337 //------------------------------------------- 00338 // The strand starts as one segment 00339 m_Segments.push_back( IC_Segment( 0, m_iNoLinks, false, true ) ); 00340 //------------------------------------------- 00341 // Create Lock Status Flags 00342 if ( ( m_prIsLocked = new bool[ m_iNoLinks + 1 ] ) == NULL ) { 00343 #ifdef TAPs_ENABLE_DEBUG 00344 std::cerr << "ERROR => ModelStrand Constructor:" 00345 << " Cannot allocate memory for strand lock flags!" 00346 << std::endl; 00347 #endif 00348 delete this; 00349 return; 00350 } 00351 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00352 m_prIsLocked[i] = false; 00353 } 00354 //--------------------------------------------------------------- 00355 #endif//TAPs_STRAND_LOCK_SEGMENTS 00356 //=============================================================== 00357 00358 //=============================================================== 00359 #ifdef TAPs_STRAND_KNOT_CONTROL 00360 //--------------------------------------------------------------- 00361 CreateKnotControl(); 00362 //--------------------------------------------------------------- 00363 #endif//TAPs_STRAND_KNOT_CONTROL 00364 //=============================================================== 00365 00366 //=============================================================== 00367 #ifdef TAPs_ADVANCED_SIMULATION 00368 //--------------------------------------------------------------- 00369 // Create Simulation Flags 00370 if ( ( m_SimFlags = new DS::SimulationFlags[ m_iNoLinks + 1 ] ) == NULL ) { 00371 #ifdef TAPs_ENABLE_DEBUG 00372 std::cerr << "ERROR => ModelStrand Constructor:" 00373 << " Cannot allocate memory for strand simulation flags!" 00374 << std::endl; 00375 #endif 00376 delete this; 00377 return; 00378 } 00379 //--------------------------------------------------------------- 00380 #endif//TAPs_ADVANCED_SIMULATION 00381 //=============================================================== 00382 00383 } //EOF: AllocateLinkProps ( Vector3<T> &posOfVertex0 ) 00384 //----------------------------------------------------------------------------- 00385 // Default constructor 00386 template <typename T> 00387 ModelStrand<T>::ModelStrand () 00388 : OpenGLModel<T>(), 00389 m_iNoLinks ( 128 ), 00390 m_tRadius ( 0.05 ), 00391 m_tLinkLength ( 0.1 ), 00392 m_tPointWeight ( 0.1 ), 00393 m_tKRatioOfStretchingAllowed ( 0.10 ), 00394 m_tKRatioOfCompressionAllowed ( 0.05 ), 00395 m_tKStretching ( 2.0 ), 00396 m_tKBending ( 0.5 ), 00397 m_tKTwisting ( 0.5 ), 00398 m_tKFriction ( 0.5 ), 00399 m_tKContact1 ( 0.5 ), 00400 m_tKContact2 ( 0.9 ), 00401 m_tKGravity ( 9.81 ), 00402 m_tMoveStepDistAllowed ( m_tRadius * 0.5 ) 00403 #ifdef TAPs_STRAND_ENABLE_DAMPING_LIMIT 00404 , uiCounterDamping( 0 ) 00405 , uiLimitCounterDamping( 100 ) 00406 #endif//TAPs_STRAND_ENABLE_DAMPING_LIMIT 00407 #ifdef TAPs_ADVANCED_SIMULATION 00408 , AdvSimID( TotalModels++ ) 00409 #endif//TAPs_ADVANCED_SIMULATION 00410 { 00411 #ifdef TAPs_USE_CUDA 00412 // Data Members for CUDA 00413 m_cudaID = 0; 00414 m_cudaVertexList = NULL; 00415 m_cudaPrevVertexList = NULL; 00416 00417 #ifdef TAPs_ADVANCED_SIMULATION 00418 m_cudaSimFlagsList = NULL; 00419 m_cudaPosConstraintList = NULL; 00420 #endif//TAPs_ADVANCED_SIMULATION 00421 #endif//TAPs_USE_CUDA 00422 00423 //---------------------------------------------------------------- 00424 AllocateLinkProps( Vector3<T>(0,0,0) ); 00425 //---------------------------------------------------------------- 00426 #ifdef TAPs_STRAND_KNOT_RECOGNITION_BY_DOWKER_NOTATION 00427 CreateDataSpaceForKnotRecognitionByDowkerNotation(); 00428 #endif//TAPs_STRAND_KNOT_RECOGNITION_BY_DOWKER_NOTATION 00429 //---------------------------------------------------------------- 00430 #ifdef TAPs_ENABLE_DEBUG 00431 std::cout << "Default ModelStrand<" << typeid(T).name() << "> with:\n" 00432 << " " << m_iNoLinks << " links with each link of length " 00433 << m_tLinkLength << " and weight " << m_tPointWeight << "\n"; 00434 #endif//TAPs_DEBUG_MODE 00435 00436 #ifdef TAPs_USE_CUDA 00437 CUDA_Initialize_All(); 00438 #endif//TAPs_USE_CUDA 00439 } 00440 //----------------------------------------------------------------------------- 00441 // Constructor 00442 template <typename T> 00443 ModelStrand<T>::ModelStrand ( int iNoLinks, T tLength, T tWeight, 00444 Vector3<T> & posOfVertex0, T tRadius ) 00445 00446 : OpenGLModel<T>(), 00447 m_iNoLinks ( iNoLinks ), 00448 m_tRadius ( tRadius ), 00449 m_tLinkLength ( tLength / iNoLinks ), 00450 m_tPointWeight ( tWeight / iNoLinks ), 00451 m_tKRatioOfStretchingAllowed ( 0.10 ), 00452 m_tKRatioOfCompressionAllowed ( 0.05 ), 00453 m_tKStretching ( 10.0 ), 00454 m_tKBending ( 0.02 ), 00455 m_tKTwisting ( 0.5 ), 00456 m_tKFriction ( 5 ), 00457 m_tKGravity ( 9.81 ), 00458 m_tKContact1 ( 0.5 ), 00459 m_tKContact2 ( 0.9 ), 00460 m_tMoveStepDistAllowed ( m_tRadius * 0.5 ) 00461 #ifdef TAPs_STRAND_ENABLE_DAMPING_LIMIT 00462 , uiCounterDamping( 0 ) 00463 , uiLimitCounterDamping( 100 ) 00464 #endif//TAPs_STRAND_ENABLE_DAMPING_LIMIT 00465 #ifdef TAPs_ADVANCED_SIMULATION 00466 , AdvSimID( TotalModels++ ) 00467 #endif//TAPs_ADVANCED_SIMULATION 00468 { 00469 #ifdef TAPs_USE_CUDA 00470 // Data Members for CUDA 00471 m_cudaID = 0; 00472 m_cudaVertexList = NULL; 00473 m_cudaPrevVertexList = NULL; 00474 00475 #ifdef TAPs_ADVANCED_SIMULATION 00476 m_cudaSimFlagsList = NULL; 00477 m_cudaPosConstraintList = NULL; 00478 #endif//TAPs_ADVANCED_SIMULATION 00479 #endif//TAPs_USE_CUDA 00480 00481 //---------------------------------------------------------------- 00482 AllocateLinkProps( posOfVertex0 ); 00483 //---------------------------------------------------------------- 00484 #ifdef TAPs_STRAND_KNOT_RECOGNITION_BY_DOWKER_NOTATION 00485 CreateDataSpaceForKnotRecognitionByDowkerNotation(); 00486 #endif//TAPs_STRAND_KNOT_RECOGNITION_BY_DOWKER_NOTATION 00487 //---------------------------------------------------------------- 00488 #ifdef TAPs_ENABLE_DEBUG 00489 std::cout << "ModelStrand<" << typeid(T).name() << "> with:\n" 00490 << " " << m_iNoLinks << " links with each link of length " 00491 << m_tLinkLength << " and weight " << m_tPointWeight << "\n"; 00492 #endif//TAPs_DEBUG_MODE 00493 00494 #ifdef TAPs_USE_CUDA 00495 CUDA_Initialize_All(); 00496 #endif//TAPs_USE_CUDA 00497 } 00498 //----------------------------------------------------------------------------- 00499 // Destructor 00500 template <typename T> 00501 ModelStrand<T>::~ModelStrand () 00502 { 00503 //---------------------------------------------------------------- 00504 if ( m_prLinkDirection ) { 00505 delete [] m_prLinkDirection; 00506 m_prLinkDirection = NULL; 00507 } 00508 //---------------------------------------------------------- 00509 if ( m_prOrigVertex ) { 00510 delete [] m_prOrigVertex; 00511 m_prOrigVertex = NULL; 00512 } 00513 00514 #ifdef TAPs_USE_EXTERNAL_ODE_SOLVER 00515 if ( m_prVertex ) { 00516 delete [] m_prVertex; 00517 m_prVertex = NULL; 00518 } 00519 if ( m_prVelocity ) { 00520 delete [] m_prVelocity; 00521 m_prVelocity = NULL; 00522 } 00523 if ( m_prForce ) { 00524 delete [] m_prForce; 00525 m_prForce = NULL; 00526 } 00527 #else //TAPs_USE_EXTERNAL_ODE_SOLVER 00528 if ( m_prVertexPositionRecord ) { 00529 for ( int i = 0; i < m_PositionCounter.GetValueHighest(); ++i ) { 00530 delete [] m_prVertexPositionRecord[i]; 00531 m_prVertexPositionRecord[i] = NULL; 00532 } 00533 delete [] m_prVertexPositionRecord; 00534 } 00535 if ( m_prVertexVelocityRecord ) { 00536 for ( int i = 0; i < m_VelocityCounter.GetValueHighest(); ++i ) { 00537 delete [] m_prVertexVelocityRecord[i]; 00538 m_prVertexVelocityRecord[i] = NULL; 00539 } 00540 delete [] m_prVertexVelocityRecord; 00541 } 00542 if ( m_prVertexForceRecord ) { 00543 for ( int i = 0; i < m_ForceCounter.GetValueHighest(); ++i ) { 00544 delete [] m_prVertexForceRecord[i]; 00545 m_prVertexForceRecord[i] = NULL; 00546 } 00547 delete [] m_prVertexForceRecord; 00548 } 00549 #endif//TAPs_USE_EXTERNAL_ODE_SOLVER 00550 00551 //---------------------------------------------------------- 00552 if ( m_prVertexPrevPos ) { 00553 delete [] m_prVertexPrevPos; 00554 m_prVertexPrevPos = NULL; 00555 } 00556 if ( m_prTempVertex1 ) { 00557 delete [] m_prTempVertex1; 00558 m_prTempVertex1 = NULL; 00559 } 00560 if ( m_prTempVertex2 ) { 00561 delete [] m_prTempVertex2; 00562 m_prTempVertex2 = NULL; 00563 } 00564 if ( m_prDegRot ) { 00565 delete [] m_prDegRot; 00566 m_prDegRot = NULL; 00567 } 00568 if ( m_prIsFixed ) { 00569 delete [] m_prIsFixed; 00570 m_prIsFixed = NULL; 00571 } 00572 00573 /* 00574 if ( m_prWasIntersect ) { 00575 delete [] m_prWasIntersect; 00576 m_prWasIntersect = NULL; 00577 } 00578 //*/ 00579 00580 if ( m_prDispVertex ) { 00581 delete [] m_prDispVertex; 00582 m_prDispVertex = NULL; 00583 } 00584 if ( m_StructForce ) { 00585 delete [] m_StructForce; 00586 m_StructForce = NULL; 00587 } 00588 //---------------------------------------------------------------- 00589 #ifdef TAPs_ENABLE_DEBUG 00590 std::cout << "ModelStrand<" << typeid(T).name() << "> Destructor\n"; 00591 #endif//TAPs_DEBUG_MODE 00592 00593 //---------------------------------------------------------------- 00594 #ifdef TAPs_STRAND_KNOT_RECOGNITION_BY_DOWKER_NOTATION 00595 DeleteDataSpaceForKnotRecognitionByDowkerNotation(); 00596 #endif//TAPs_STRAND_KNOT_RECOGNITION_BY_DOWKER_NOTATION 00597 //---------------------------------------------------------------- 00598 00599 //---------------------------------------------------------------- 00600 // For simulation 00601 #ifdef TAPs_USE_EXTERNAL_ODE_SOLVER 00602 delete m_prODESolver; 00603 #endif//TAPs_USE_EXTERNAL_ODE_SOLVER 00604 delete m_BVHTree; 00605 //---------------------------------------------------------------- 00606 00607 //=============================================================== 00608 #ifdef TAPs_STRAND_KNOT_CONTROL 00609 //--------------------------------------------------------------- 00610 DeleteKnotControl(); 00611 //--------------------------------------------------------------- 00612 #endif//TAPs_STRAND_KNOT_CONTROL 00613 //=============================================================== 00614 00615 //=============================================================== 00616 #ifdef TAPs_USE_CUDA 00617 //--------------------------------------------------------------- 00618 CUDA_Cleanup_All(); 00619 //--------------------------------------------------------------- 00620 #endif//TAPs_USE_CUDA 00621 //=============================================================== 00622 00623 //=============================================================== 00624 #ifdef TAPs_ADVANCED_SIMULATION 00625 //--------------------------------------------------------------- 00626 // Create Simulation Flags 00627 if ( m_SimFlags ) { 00628 delete [] m_SimFlags; 00629 m_SimFlags = NULL; 00630 } 00631 //--------------------------------------------------------------- 00632 #endif//TAPs_ADVANCED_SIMULATION 00633 //=============================================================== 00634 } 00635 //============================================================================= 00636 // Get/Set Fn(s) 00637 //----------------------------------------------------------------------------- 00638 template <typename T> 00639 inline void ModelStrand<T>::SetFixStatusOfPtNo ( int i, bool b ) 00640 { 00641 if ( i < 0 || m_iNoLinks < i ) return; 00642 00643 if ( m_prIsFixed[i] == b ) return; // m_prIsFixed[i] is already b status 00644 if ( b ) { // add its # from the set of fixed points 00645 m_prIsFixed[i] = true; 00646 m_setOfFixedPts.insert( i ); 00647 #ifdef TAPs_ADVANCED_SIMULATION 00648 //m_SimFlags[i].SetSimulationConstraints( TAPs::Enum::AddOn::FIXED ); 00649 #endif//TAPs_ADVANCED_SIMULATION 00650 } 00651 else { // remove its # from the set of fixed points 00652 m_prIsFixed[i] = false; 00653 m_setOfFixedPts.erase( i ); 00654 #ifdef TAPs_ADVANCED_SIMULATION 00655 //m_SimFlags[i].SetSimulationConstraints( TAPs::Enum::AddOn::CLEARED ); 00656 #endif//TAPs_ADVANCED_SIMULATION 00657 } 00658 } 00659 //----------------------------------------------------------------------------- 00660 template <typename T> 00661 inline void ModelStrand<T>::ToggleFixStatusOfPtNo ( int i ) 00662 { 00663 SetFixStatusOfPtNo( i, !GetFixStatusOfPtNo(i) ); 00664 } 00666 template <typename T> 00667 void ModelStrand<T>::FixSegment ( int start, int end ) 00668 { 00669 if ( start < 0 ) start = 0; 00670 if ( end > m_iNoLinks ) end = m_iNoLinks; 00671 while ( start <= end ) { 00672 SetFixStatusOfPtNo( start, true ); 00673 ++start; 00674 } 00675 } 00676 //----------------------------------------------------------------------------- 00678 template <typename T> 00679 void ModelStrand<T>::UnfixSegment ( int start, int end ) 00680 { 00681 if ( start < 0 ) start = 0; 00682 if ( end > m_iNoLinks ) end = m_iNoLinks; 00683 while ( start <= end ) { 00684 SetFixStatusOfPtNo( start, false ); 00685 ++start; 00686 } 00687 } 00688 //----------------------------------------------------------------------------- 00689 template <typename T> 00690 inline Vector3<T> const & ModelStrand<T>::RetPointPosition ( int i ) const 00691 { 00692 return m_prVertex[i]; 00693 } 00694 //----------------------------------------------------------------------------- 00695 template <typename T> 00696 inline Vector3<T> & ModelStrand<T>::RetPointPosition ( int i ) 00697 { 00698 return m_prVertex[i]; 00699 } 00700 //----------------------------------------------------------------------------- 00701 template <typename T> 00702 inline Vector3<T> ModelStrand<T>::GetPointPosition ( int i ) const 00703 { 00704 return m_prVertex[i]; 00705 } 00706 //----------------------------------------------------------------------------- 00707 template <typename T> 00708 inline void ModelStrand<T>::SetPointPosition ( 00709 int i, const Vector3<T> & position, 00710 //T tMoveDistanceLimit, 00711 MultiBoundingVolume<T> const * const pMBV, 00712 TransformationSupport<T> const * const pTransform 00713 ) 00714 { 00715 #ifdef TAPs_STRAND_ENABLE_DAMPING_LIMIT 00716 // Reset counter for damping (for stopping vibration) 00717 uiCounterDamping = 0; 00718 #endif//TAPs_STRAND_ENABLE_DAMPING_LIMIT 00719 00720 // Save Previous Positions for roll back position 00721 //SavePreviousPositions(); 00722 00723 //-------------------------------------------------------------------- 00724 // Adjust the time 00725 static TAPs::Simulation::SimClock<Real> gClock( 0, 1E10, 0, 0.01 ); 00726 static Real prevTime = glutGet( GLUT_ELAPSED_TIME ); 00727 static Real currTime; 00728 00729 //SetFixStatusOfPtNo( i, true ); 00730 Vector3<T> u = position - m_prVertex[i]; 00731 00732 //* 00733 //m_tMoveStepDistAllowed = m_tRadius * 0.2; 00734 //T moveAllowed = m_tRadius * 200; 00735 T moveDistance = u.Length(); 00736 u = u.Normalized() * m_tMoveStepDistAllowed; 00737 T moveStep = moveDistance / m_tMoveStepDistAllowed; 00738 //u = u.Normalized() * tMoveDistanceLimit; 00739 //T moveStep = moveDistance / tMoveDistanceLimit; 00740 // T moveStep = 1; 00741 00742 // Limit number of steps 00743 const unsigned int LIMIT_STEPS = 250; 00744 unsigned int currentStep = 0; 00745 //---------------------------------------------------------------- 00746 //* 00747 00748 while ( moveStep > Math<T>::ZERO && ++currentStep < LIMIT_STEPS ) { 00749 00750 // Save Previous Positions for roll back position 00751 //SavePreviousPositions(); 00752 00753 if ( moveStep > Math<T>::ONE ) { 00754 moveStep -= Math<T>::ONE; 00755 } 00756 else { 00757 u *= moveStep; 00758 moveStep = Math<T>::ZERO; 00759 } 00760 //------------------------------------------------------ 00761 m_prVertex[i] += u; 00762 //-------------------------------------------------------------------- 00763 00764 //-------------------------------------------------------------------- 00765 //currTime = glutGet( GLUT_ELAPSED_TIME ); 00766 //gClock.step = (currTime - prevTime) / static_cast<Real>( 1000.0 ); 00767 //prevTime = currTime; 00768 //AdvanceSimulation( gClock.current, gClock.current + gClock.step ); 00769 AdvanceSimulation( 0.0, 0.005 ); 00770 } 00771 } 00772 //============================================================================= 00773 // Helper Fn(s) 00774 //----------------------------------------------------------------------------- 00775 template <typename T> 00776 void ModelStrand<T>::SetDisplayLinks () 00777 { 00778 m_prDispVertex[0] = m_prVertex[0]; 00779 for ( int i = 1, p = 0; i < m_iNoLinks; ++i ) { 00780 m_prDispVertex[++p] = (m_prVertex[i-1] + 3*m_prVertex[i]) / 4; 00781 m_prDispVertex[++p] = (3*m_prVertex[i] + m_prVertex[i+1]) / 4; 00782 } 00783 m_prDispVertex[m_iNoLinks*2 - 1] = m_prVertex[m_iNoLinks]; 00784 00785 //---------------------------------------------------------------- 00786 // Current positions ==> Previous positions 00787 // for ( int i = 0; i <= m_iNoLinks; ++i ) { 00788 // m_prVertexPrevPos[i] = m_prVertex[i]; 00789 // } 00790 } 00791 //============================================================================= 00792 // For Simulation 00793 //----------------------------------------------------------------------------- 00794 //----------------------------------------------------------------------------- 00795 // DxDt 00796 template <typename T> 00797 bool ModelStrand<T>::DxDt ( 00798 T dt, // i/p: time step 00799 Simulation::VectorSet<T> &x, // i/p: array x = {pos, vel} 00800 Simulation::VectorSet<T> &xdot, // o/p: array xdot = {vel, accel} 00801 void *userData // o/p: array of user data 00802 ) 00803 { 00804 //------------------------------------------------------ 00805 // Convert userData ptr to ModelStrand ptr 00806 ModelStrand<T> *pThis = static_cast<ModelStrand<T> *>( userData ); 00807 assert( pThis ); 00808 /* 00809 //------------------------------------------------------ 00810 for ( int i = 0; i <= pThis->m_iNoLinks; ++i ) { 00811 if ( pThis->m_prIsFixed[i] ) { 00812 pThis->m_prVelocity[i][0] = 00813 pThis->m_prVelocity[i][1] = 00814 pThis->m_prVelocity[i][2] = 00815 pThis->m_prForce[i][0] = 00816 pThis->m_prForce[i][1] = 00817 pThis->m_prForce[i][2] = 0; 00818 } 00819 else { 00820 //pThis->m_prForce[i] = pThis->m_StructForce[i].gravity; 00821 //pThis->m_prVelocity[i][1] = pThis->m_prForce[i][1] * 00822 // pThis->m_prVertex[i][1] * 00823 // dt; 00824 } 00825 } 00826 //*/ 00827 //------------------------------------------------------ 00828 // Copy data from x array into state variables 00829 //pThis->ArrayToState( &x[0] ); 00830 //------------------------------------------------------ 00831 pThis->DdtStateToArray( &xdot[0], dt ); 00832 //pThis->ClearForces(); 00833 //------------------------------------------------------ 00834 00835 /* 00836 for ( i = 0; i <= pThis->m_iNoLinks; ++i ) { 00837 //if ( pThis->m_prVertex[i][1] > 2 * pThis->m_tRadius ) { 00838 if ( false ) { 00839 // pThis->m_prForce[i] += pThis->CalForceGravity( i ); 00840 } 00841 else { 00842 // pThis->m_prForce[i][1] = 0; 00843 // pThis->m_prVelocity[i][1] = 0; 00844 pThis->m_prVertex[i][1] = 0; 00845 } 00846 } 00847 //*/ 00848 00849 return true; 00850 } 00851 //----------------------------------------------------------------------------- 00852 // StateToArray 00853 template <typename T> 00854 void ModelStrand<T>::StateToArray ( T *dst ) 00855 { 00856 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00857 *(dst++) = m_prVertex[i][0]; 00858 *(dst++) = m_prVertex[i][1]; 00859 *(dst++) = m_prVertex[i][2]; 00860 *(dst++) = m_prVelocity[i][0]; 00861 *(dst++) = m_prVelocity[i][1]; 00862 *(dst++) = m_prVelocity[i][2]; 00863 } 00864 } 00865 //----------------------------------------------------------------------------- 00866 // ArrayToState 00867 template <typename T> 00868 void ModelStrand<T>::ArrayToState ( T *src ) 00869 { 00870 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00871 m_prVertex[i][0] = *(src++); 00872 m_prVertex[i][1] = *(src++); 00873 m_prVertex[i][2] = *(src++); 00874 m_prVelocity[i][0] = *(src++); 00875 m_prVelocity[i][1] = *(src++); 00876 m_prVelocity[i][2] = *(src++); 00877 } 00878 } 00879 //----------------------------------------------------------------------------- 00880 // DdtStateToArray 00881 template <typename T> 00882 void ModelStrand<T>::DdtStateToArray ( T *xdot, T dt ) 00883 { 00884 //------------------------------------------- 00885 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00886 /*if ( m_prIsFixed[i] ) { 00887 *(xdot++) = 00888 *(xdot++) = 00889 *(xdot++) = 00890 *(xdot++) = 00891 *(xdot++) = 00892 *(xdot++) = 0; 00893 } 00894 else {*/ 00895 //m_prForce[i] = m_StructForce[i].gravity; 00896 //m_prVelocity[i][1] = m_prForce[i][1] * m_prVertex[i][1] * dt; 00897 //---------------------------------------- 00898 *(xdot++) = m_prVelocity[i][0]; 00899 *(xdot++) = m_prVelocity[i][1]; 00900 *(xdot++) = m_prVelocity[i][2]; 00901 *(xdot++) = m_prForce[i][0] / m_tPointWeight; 00902 *(xdot++) = m_prForce[i][1] / m_tPointWeight; 00903 *(xdot++) = m_prForce[i][2] / m_tPointWeight; 00904 //} 00905 } 00906 } 00907 //* 00908 //----------------------------------------------------------------------------- 00909 // ClearForces 00910 template <typename T> 00911 void ModelStrand<T>::ClearForces () 00912 { 00913 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00914 m_prForce[i].SetXYZ( 0, 0, 0 ); 00915 } 00916 } 00917 //----------------------------------------------------------------------------- 00918 // ClearVelocities 00919 template <typename T> 00920 void ModelStrand<T>::ClearVelocities () 00921 { 00922 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00923 m_prVelocity[i].SetXYZ( 0, 0, 0 ); 00924 } 00925 } 00926 //*/ 00927 //----------------------------------------------------------------------------- 00928 // SimGravity 00929 template <typename T> 00930 void ModelStrand<T>::SimGravity ( T tCurrent, T tNext ) 00931 { 00932 static int beingAtLinkNo = 2; 00933 T LIMIT = 0.1; 00934 T dt = tNext - tCurrent; // in seconds 00935 if ( dt > LIMIT ) dt = LIMIT; 00936 00937 //* 00938 int count = 0; 00939 //---------------------------------------------------------------- 00940 for ( int i = beingAtLinkNo; i <= m_iNoLinks; ++i ) { 00941 if ( m_prIsFixed[i] == false && 00942 m_prVertex[i][1] > 6 * m_tRadius ) { 00943 ++count; 00944 } 00945 } 00946 //---------------------------------------------------------------- 00947 if ( count > 0 ) { 00948 for ( int i = beingAtLinkNo; i <= m_iNoLinks; ++i ) { 00949 if ( m_prIsFixed[i] == false ) { 00950 if ( m_prVertex[i][1] > 3 * m_tRadius ) { 00951 //m_prVertex[i][1] -= Physics_SI::K::g*m_tPointWeight * (tNext - tCurrent) 00952 // / static_cast<T>( 1000 ); 00953 m_prVertex[i][1] -= Physics_SI::K::g*m_tPointWeight * dt; 00954 } 00955 if ( m_prVertex[i][1] < m_tRadius ) { 00956 m_prVertex[i][1] = m_tRadius; 00957 } 00958 } 00959 } 00960 } 00961 //*/ 00962 } 00963 //----------------------------------------------------------------------------- 00964 // AdvanceSimulation 00965 template <typename T> 00966 void ModelStrand<T>::AdvanceSimulation ( T tCurrent, T tNext ) 00967 { 00968 //std::cout << "FILE: " << __FILE__ << " LINE: " << __LINE__ << " -- AdvanceSimulation( T tCurrent, T tNext )\n"; 00969 00970 #ifdef TAPs_STRAND_DEBUG 00971 T currLen = GetCurrentLength(); 00972 T ideaLen = GetLength(); 00973 std::cout << "Strand Length:" << " (current) " << currLen << " (idea) " << ideaLen << "\n"; 00974 std::cout << " Len diff: " << currLen - ideaLen << "\n"; 00975 #endif//TAPs_STRAND_DEBUG 00976 00977 #ifdef TAPs_STRAND_ENABLE_DAMPING_LIMIT 00978 if ( uiLimitCounterDamping < ++uiCounterDamping ) return; 00979 #endif//TAPs_STRAND_ENABLE_DAMPING_LIMIT 00980 00981 //int steps = 1; 00982 //T currentTime = tCurrent; 00983 //T timeStep = tNext / steps; 00984 //T nextTime = tCurrent + timeStep; 00985 //for ( int st = 0; st < steps; ++st ) 00986 { 00987 //------------------------------------------------------ 00988 //* 00989 //------------------------------------------------------ 00990 for ( int i = 0; i <= m_iNoLinks; ++i ) { 00991 if ( m_prIsFixed[i] ) { 00992 m_prVelocity[i][0] = 00993 m_prVelocity[i][1] = 00994 m_prVelocity[i][2] = 00995 m_prForce[i][0] = 00996 m_prForce[i][1] = 00997 m_prForce[i][2] = 0; 00998 } 00999 else { 01000 //pThis->m_prForce[i] = pThis->m_StructForce[i].gravity; 01001 //pThis->m_prVelocity[i][1] = pThis->m_prForce[i][1] * 01002 // pThis->m_prVertex[i][1] * 01003 // dt; 01004 m_prForce[i].SetXYZ( 0, 0, 0 ); 01005 } 01006 } 01007 //*/ 01008 01009 01010 //* 01011 // This is put in AdvanceSimulation Fn 01012 //------------------------------------------------------------------ 01013 // Reset Forces and Velocities 01014 // for ( int i = 0; i <= m_iNoLinks; ++i ) { 01015 // m_prForce[i].SetXYZ( 0, 0, 0 ); 01016 // //m_prVelocity[i].SetXYZ( 0, 0, 0 ); 01017 // } 01018 //------------------------------------------------------ 01019 // UpdateBVHTree(); 01020 // CheckSelfIntersections(); 01021 //------------------------------------------------------ 01022 //*/ 01023 01024 //=============================================================== 01025 //--------------------------------------------------------------- 01026 #ifdef TAPs_USE_EXTERNAL_ODE_SOLVER 01027 //--------------------------------------------------------------- 01028 01029 //------------------------------------------------- 01030 StateToArray( &x0[0] ); 01031 SimByForce( tCurrent, tNext ); 01032 // ODE Solver 01033 m_prODESolver->Solve( x0, xEnd, tCurrent, tNext, DxDt, this ); 01034 // Copy d/dt X(tNext) into state variables xEnd 01035 ArrayToState( &xEnd[0] ); 01036 //------------------------------------------------- 01037 01038 //--------------------------------------------------------------- 01039 #else //TAPs_USE_EXTERNAL_ODE_SOLVER 01040 //--------------------------------------------------------------- 01041 01042 01043 //------------------------------------------------- 01044 // Sim by Verlet Intetration using CUDA 01045 //------------------------------------------------- 01046 #ifdef TAPs_USE_CUDA 01047 01048 //PrintDebug_ConnectionList(); 01049 //PrintDebug(); 01050 01051 // Copy the (current) vertex positions of the object to memory for transfering to CUDA. 01052 CUDA_CopyVertexToMem(); 01053 #ifdef TAPs_ADVANCED_SIMULATION 01054 CUDA_CopySimFlagsToMem(); 01055 CUDA_CopyPosConstraintToMem(); 01056 #endif//TAPs_ADVANCED_SIMULATION 01057 //CUDA_CopyPrevVertexToMem(); 01058 01059 // DEBUG 01060 for ( int i = 0; i <= m_iNoLinks; i+=m_iNoLinks ) { 01061 int idx = i*4; 01062 printf( "m_cudaVertexList# %d : %g %g %g %g\n", i, m_cudaVertexList[idx], m_cudaVertexList[idx+1], m_cudaVertexList[idx+2], m_cudaVertexList[idx+3] ); 01063 printf( "m_cudaPrevVertexList# %d: %g %g %g %g\n", i, m_cudaPrevVertexList[idx], m_cudaPrevVertexList[idx+1], m_cudaPrevVertexList[idx+2], m_cudaPrevVertexList[idx+3] ); 01064 } 01065 01066 // Call the wrapper function for 01067 #ifdef TAPs_ADVANCED_SIMULATION 01068 TAPs::CUDA::Global__ModelStrand_AdvSim_ADVSIM( 01069 m_cudaID, 01070 m_iNoLinks+1, 01071 64, 01072 tCurrent, 01073 0.001*10, //GetPredefinedTimeStep(), //!< time step 01074 10, //GetNumSimSubSteps(), //!< number of sub-steps 01075 m_tPointWeight, 01076 GetKStretching(), 01077 GetKFriction(), 01078 GetLinkLength(), 01079 m_cudaVertexList, 01080 m_cudaPrevVertexList, 01081 m_cudaSimFlagsList, 01082 m_cudaPosConstraintList 01083 ); 01084 #else //TAPs_ADVANCED_SIMULATION 01085 TAPs::CUDA::Global__ModelStrand_AdvSim( 01086 m_cudaID, 01087 m_iNoLinks+1, 01088 64, 01089 tCurrent, 01090 0.001*10, //GetPredefinedTimeStep(), //!< time step 01091 10, //GetNumSimSubSteps(), //!< number of sub-steps 01092 m_tPointWeight, 01093 GetKStretching(), 01094 GetKFriction(), 01095 GetLinkLength(), 01096 m_cudaVertexList, 01097 m_cudaPrevVertexList 01098 //m_cudaHomeVertexList, 01099 //m_cudaVertexConnectionList, 01100 ); 01101 #endif//TAPs_ADVANCED_SIMULATION 01102 01103 // The new vertex positions are returned by CUDA to memory for previous vertex positions. 01104 // So the new vertex positions must be copied to the vertex positions of the object. 01105 CUDA_CopyMemToPrevVertex(); 01106 // Then the previous and current vertex pointers (that point to memory for transfering to CUDA) are swapped. 01107 // So that now the previous becomes current and the current becomes previous. 01108 CUDA_SwapBuffers(); 01109 01110 #ifdef TAPs_ADVANCED_SIMULATION 01111 // The new strand's simulation flags list is returned by CUDA. 01112 // It must be copied to the simulation flags list of the strand. 01113 CUDA_CopyMemToSimFlags(); 01114 CUDA_CopyMemToPosConstraint(); 01115 01116 // NEED TO CHANGE THE VALUES STORED IN m_pAdvSimData 01117 01118 #endif//TAPs_ADVANCED_SIMULATION 01119 01120 01121 GetBVHTree()->Update(); // commented out to rely on CDR to update the collided BVNodes 01122 01123 #else //TAPs_USE_CUDA 01124 //------------------------------------------------- 01125 // Sim by Verlet Intetration using CUDA 01126 //------------------------------------------------- 01127 01128 01129 //------------------------------------------------- 01130 // Sim by Euler Intetration 01131 //------------------------------------------------- 01132 #ifdef TAPs_USE_INTERNAL_ODE_SOLVER_EULER 01133 // Remark: here ' represents next value, not differentiation 01134 // a' = f/m 01135 // v' = v + a'*t = v + f*t/m 01136 // x' = x + v'*t 01137 01138 T t = tNext - tCurrent; 01139 //T t = 0.005; 01140 01141 // ERROR WHY??? 01142 //CycleBuffer(); // make next (a',v',x') become current and current become previous 01143 01144 //--------------------------------------- 01145 // Calculate F 01146 // For collision we use geometric constraints instead of (external) force constraints 01147 SimByForce( tCurrent, tNext ); // Calculate F_internal 01148 01149 //--------------------------------------- 01150 // Calculate V' and X' 01151 #ifdef TAPs_STRAND_LOCK_SEGMENTS 01152 // For segment# 0 01153 { 01154 unsigned int s = 0; 01155 if ( !m_Segments[s].isLocked ) { 01156 for ( unsigned int i = m_Segments[s].start; i <= m_Segments[s].end; ++i ) 01157 { 01158 if ( !m_prIsFixed[i] ) { 01159 m_prVelocity[i] = m_prVelocityPrev[i] + m_prForcePrev[i]*t/m_tPointWeight; 01160 m_prVertex[i] = m_prVertexPrev[i] + m_prVelocityPrev[i]*t; 01161 } 01162 } 01163 } 01164 } 01165 // For segment# > 0 01166 for ( unsigned int s = 1; s < m_Segments.size(); ++s ) { 01167 if ( !m_Segments[s].isLocked ) { 01168 for ( unsigned int i = m_Segments[s].start; i <= m_Segments[s].end; ++i ) 01169 #else //TAPs_STRAND_LOCK_SEGMENTS 01170 { 01171 { 01172 for ( int i = 0; i < m_iNoLinks+1; ++i ) 01173 #endif//TAPs_STRAND_LOCK_SEGMENTS 01174 { 01175 if ( !m_prIsFixed[i] ) { 01176 m_prVelocity[i] = m_prVelocityPrev[i] + m_prForcePrev[i]*t/m_tPointWeight; 01177 m_prVertex[i] = m_prVertexPrev[i] + m_prVelocityPrev[i]*t; 01178 } 01179 } 01180 } 01181 } 01182 01183 #endif//TAPs_USE_INTERNAL_ODE_SOLVER_EULER 01184 //------------------------------------------------- 01185 01186 #endif //TAPs_USE_CUDA 01187 01188 //--------------------------------------------------------------- 01189 #endif//TAPs_USE_EXTERNAL_ODE_SOLVER 01190 //--------------------------------------------------------------- 01191 //=============================================================== 01192 01193 UpdateBVHTree(); 01194 CheckSelfIntersections(); 01195 //------------------------------------------------------ 01196 } 01197 } 01198 //----------------------------------------------------------------------------- 01199 // AdvanceSimulation 01200 template <typename T> 01201 void ModelStrand<T>::AdvanceSimulation ( Simulation::SimClock<T> & simClock ) 01202 { 01203 std::cout << "FILE: " << __FILE__ << " LINE: " << __LINE__ << " -- Not Implemented Yet!\n"; 01204 } 01205 //----------------------------------------------------------------------------- 01206 01207 01208 //============================================================================= 01209 // Collision Detection 01210 //----------------------------------------------------------------------------- 01211 template <typename T> 01212 bool ModelStrand<T>::TestOverlapWith ( BVHTree<T> const * const that ) 01213 { 01214 m_svCollidedNode.clear(); 01215 m_svCollidedNodeThat.clear(); 01216 //-------------------------------------------------------------------- 01217 bool result = GetBVHTree()->TestOverlapWithTillLeafNodes( that ); 01218 if ( !result ) return result; 01219 //-------------------------------------------------------------------- 01220 BVHNode<T> * cylinder; 01221 BVHNode<T> * triangle; 01222 //-------------------------------------------------------------------- 01223 int size = static_cast<int>( GetBVHTree()->GetListOfCollidedNodes().size() ); 01224 int linkNo; 01225 for ( int i = 0; i < size; ++i ) { 01226 cylinder = GetBVHTree()->GetListOfCollidedNodes()[i]; 01227 triangle = GetBVHTree()->GetListOfCollidedNodesThat()[i]; 01228 linkNo = cylinder->GetID(); 01229 HEFace<T> * heFace = triangle->GetAPrimitiveHalfEdgeFace(); 01230 std::vector< HEVertex<T> * const > vertices = heFace->GetPtrsToVertices(); 01231 result = CGMath<T>::FindIntersectionCylinderTriangle( 01232 GetPointPosition( linkNo ), GetPointPosition( linkNo+1 ), GetRadius(), 01233 vertices[0]->GetPosition(), 01234 vertices[1]->GetPosition(), 01235 vertices[2]->GetPosition() ); 01236 01237 if ( result ) { 01238 m_svCollidedNode.push_back( GetBVHTree()->GetListOfCollidedNodes()[i] ); 01239 m_svCollidedNodeThat.push_back( GetBVHTree()->GetListOfCollidedNodesThat()[i] ); 01240 } 01241 } 01242 //-------------------------------------------------------------------- 01243 if ( static_cast<int>( m_svCollidedNode.size() ) > 0 ) return true; 01244 else return false; 01245 } 01246 01247 //----------------------------------------------------------------------------- 01248 // BuildBVHTree 01249 template <typename T> 01250 void ModelStrand<T>::BuildBVHTree () 01251 { 01252 m_BVHTree = NULL; 01253 int numOfNodes = -1; 01254 //---------------------------------------------------------------- 01255 Vector3<T> center; 01256 01257 #ifdef TAPs_DEBUG_MODE 01258 std::cout << "m_tRadius: " << m_tRadius << std::endl; 01259 std::cout << "m_tLinkLength: " << m_tLinkLength << std::endl; 01260 #endif//TAPs_DEBUG_MODE 01261 01262 T radius = m_tRadius + m_tLinkLength/2.0; 01263 01264 #ifdef TAPs_DEBUG_MODE 01265 std::cout << "radius: " << radius << std::endl; 01266 #endif//TAPs_DEBUG_MODE 01267 01268 //---------------------------------------------------------------- 01269 // Create Leaf Nodes 01270 BVHNode<T> **nodeList = new BVHNode<T> *[m_iNoLinks]; 01271 for ( int i = 0; i < m_iNoLinks; ++i ) { 01272 //nodeList[i] = new BVHNode<T>( TAPs::Enum::BVH_NODE_BINARY_SPHERE, ++numOfNodes, NULL, NULL ); 01273 //nodeList[i] = new BVHNode<T>( TAPs::Enum::BVH_NODE_BINARY_SPHERE, ++numOfNodes, NULL, NULL ); 01274 nodeList[i] = new BVHNodeLeafHalfEdgeAPrim<T>( 01275 TAPs::Enum::BVH_NODE_LEAF_SPHERE_HALFEDGE_APRIM, 01276 ++numOfNodes, NULL ); 01277 // nodeList[i] = new BVHNodeLeafHalfEdgePrims<T>( 01278 // TAPs::Enum::BVH_NODE_LEAF_SPHERE_HALFEDGE_PRIMS, 01279 // ++numOfNodes, NULL ); 01280 01281 nodeList[i]->SetRadius( radius ); 01282 nodeList[i]->SetCenter( (m_prVertex[i] + m_prVertex[i+1]) / 2.0 ); 01283 } 01284 //---------------------------------------------------------------- 01285 // Create Hierarchy Nodes 01286 m_BVHTree = BuildBVHTreeRecursively( numOfNodes+1, nodeList, m_iNoLinks ); 01287 01288 #ifdef TAPs_DEBUG_MODE 01289 std::cout << *m_BVHTree << std::endl; 01290 #endif//TAPs_DEBUG_MODE 01291 } 01292 //----------------------------------------------------------------------------- 01293 // BuildBVHTreeRecursively 01294 template <typename T> 01295 BVHTree<T> * ModelStrand<T>::BuildBVHTreeRecursively ( 01296 int startID, 01297 BVHNode<T> ** childNodeList, 01298 int numOfChildNodes ) 01299 { 01300 BVHNode<T> ** parentNodeList; 01301 if ( numOfChildNodes > 1 ) { 01302 int numOfParentNodes; 01303 if ( numOfChildNodes % 2 == 0 ) { 01304 numOfParentNodes = numOfChildNodes/2; 01305 parentNodeList = new BVHNode<T> *[ numOfParentNodes ]; 01306 for ( int i = 0, p = 0; i < numOfChildNodes; i+=2, ++p, ++startID ) { 01307 parentNodeList[p] = new BVHNode<T>( 01308 TAPs::Enum::BVH_NODE_BINARY_SPHERE, 01309 startID, NULL, NULL ); 01310 parentNodeList[p]->Child( 0, childNodeList[i] ); 01311 parentNodeList[p]->Child( 1, childNodeList[i+1] ); 01312 } 01313 } 01314 else { 01315 numOfParentNodes = numOfChildNodes/2 + 1; 01316 parentNodeList = new BVHNode<T> *[ numOfParentNodes ]; 01317 for ( int i = 0, p = 0; i < numOfChildNodes-1; i+=2, ++p, ++startID ) { 01318 parentNodeList[p] = new BVHNode<T>( 01319 TAPs::Enum::BVH_NODE_BINARY_SPHERE, 01320 startID, NULL, NULL ); 01321 parentNodeList[p]->Child( 0, childNodeList[i] ); 01322 parentNodeList[p]->Child( 1, childNodeList[i+1] ); 01323 } 01324 parentNodeList[numOfParentNodes-1] = childNodeList[numOfChildNodes-1]; 01325 } 01326 delete [] childNodeList; 01327 return BuildBVHTreeRecursively( startID, parentNodeList, numOfParentNodes ); 01328 } 01329 else { 01330 BVHTree<T> * tree = new BVHTree_BinarySphere<T>( GetTransform(), 01331 /*TAPs::Enum::BVH_TREE_BINARY_SPHERE,*/ startID, childNodeList[0] ); 01332 delete [] childNodeList; 01333 return tree; 01334 } 01335 } 01336 //----------------------------------------------------------------------------- 01337 // UpdateBVHTree 01338 template <typename T> 01339 void ModelStrand<T>::UpdateBVHTree () 01340 { 01341 if ( m_BVHTree->Root() ) { 01342 UpdateBVHNodeRecursively( m_BVHTree->Root() ); 01343 } 01344 } 01345 //----------------------------------------------------------------------------- 01346 // UpdateBVHNodeRecursively 01347 template <typename T> 01348 void ModelStrand<T>::UpdateBVHNodeRecursively ( BVHNode<T> * node ) 01349 { 01350 if ( node->Child(0) ) { 01351 UpdateBVHNodeRecursively( node->Child(0) ); 01352 } 01353 if ( node->Child(1) ) { 01354 UpdateBVHNodeRecursively( node->Child(1) ); 01355 } 01356 //---------------------------------------------------------------- 01357 if ( node->Child(0) == NULL && node->Child(1) == NULL ) { 01358 int id = node->GetID(); 01359 node->SetRadius( (m_prVertex[id] - m_prVertex[id+1]).Length()/2.0 + m_tRadius ); 01360 node->SetCenter( (m_prVertex[id] + m_prVertex[id+1]) / 2.0 ); 01361 } 01362 else { 01363 node->Update(); 01364 } 01365 } 01366 //----------------------------------------------------------------------------- 01367 // CheckSelfIntersections 01368 // Assume no intersections between immediate adjacent links 01369 // Assume a BVH node either has both children or none, therefore 01370 // checking either it has a left or right child is enough to determine 01371 // whether it is a leaf node or not. 01372 template <typename T> 01373 void ModelStrand<T>::CheckSelfIntersections () 01374 { 01375 #ifdef TAPs_CURRENT_DEBUG 01376 g_iDebugCounter01 = 0; 01377 #endif 01378 //---------------------------------------------------------------- 01379 //std::cout << "\n\nCheckSelfIntersections Result:\n"; 01380 //if ( !m_BVHTree->Root() ) return; 01381 //BVHNode<T> * leftNode = m_BVHTree->Root()->Child(0); 01382 //BVHNode<T> * rightNode = m_BVHTree->Root()->Child(1); 01383 //---------------------------------------------------------------- 01384 //CheckSelfIntersectionsNextLevelRecursively( leftNode, rightNode ); 01385 01386 /* 01387 for ( int i = 0; i < m_iNoLinks; ++i ) { 01388 if ( m_prWasIntersect[i] > 0 ) { 01389 --m_prWasIntersect[i]; 01390 } 01391 } 01392 //*/ 01393 01394 //---------------------------------------------------------------- 01395 CheckSelfIntersectionsNextLevelRecursively( m_BVHTree->Root()->Child(0), 01396 m_BVHTree->Root()->Child(1) ); 01397 //---------------------------------------------------------------- 01398 01399 #ifdef TAPs_CURRENT_DEBUG 01400 if ( g_iDebugCounter01 > 10 ) { 01401 sprintf( g_cstrDebugArray[32], "Possibly a knot is formed!!!" ); 01402 } 01403 else { 01404 sprintf( g_cstrDebugArray[32], "No knots" ); 01405 } 01406 // Clear the less of the string rows 01407 for ( ; g_iDebugCounter01 < 32; ++g_iDebugCounter01 ) { 01408 sprintf( g_cstrDebugArray[g_iDebugCounter01], "" ); 01409 } 01410 #endif 01411 } // EOF: CheckSelfIntersections () 01412 //----------------------------------------------------------------------------- 01413 // CheckSelfIntersectionsNextLevelRecursively 01414 // Assume no intersections between immediate adjacent links 01415 // Assume a BVH node either has both children or none, therefore 01416 // checking either it has a left or right child is enough to determine 01417 // whether it is a leaf node or not. 01418 template <typename T> 01419 void ModelStrand<T>::CheckSelfIntersectionsNextLevelRecursively ( 01420 BVHNode<T> * node1, 01421 BVHNode<T> * node2 ) 01422 { 01423 CheckSelfIntersectionsRecursively( node1, node2 ); 01424 if ( node1->Child(0) ) 01425 CheckSelfIntersectionsNextLevelRecursively( node1->Child(0), node1->Child(1) ); 01426 if ( node2->Child(0) ) 01427 CheckSelfIntersectionsNextLevelRecursively( node2->Child(0), node2->Child(1) ); 01428 } 01429 //----------------------------------------------------------------------------- 01430 // CheckSelfIntersectionsRecursively 01431 // Assume no intersections between immediate adjacent links 01432 // Use the fact that the ids of sphere bvh leaf nodes are the same as 01433 // the link id and 01434 template <typename T> 01435 T ModelStrand<T>::CheckSelfIntersectionsRecursively ( 01436 BVHNode<T> * node1, 01437 BVHNode<T> * node2 ) 01438 { 01439 static T LinkDiameter = static_cast<T>(2.0) * m_tRadius; 01440 static T epsilon = m_tRadius * static_cast<T>(0.05); // for collision response 01441 //---------------------------------------------------------------- 01442 //if ( !node1 || !node2 ) return Math<T>::MAX; 01443 if ( !node1->Child(0) && !node2->Child(0) && 01444 ( abs(node1->GetID() - node2->GetID()) == 1 ) ) 01445 { 01446 return DBL_MAX; 01447 } 01448 //---------------------------------------------------------------- 01449 T overlap = node1->TestOverlapSphereWithSphere_NoPrimitiveTests( node2 ); 01450 //std::cout << "Node#" << node1->GetID() << " intersects with " 01451 // << "Node#" << node2->GetID() << " by " << overlap << "\n"; 01452 //---------------------------------------------------------------- 01453 if ( overlap < DBL_MIN ) { 01454 if ( node2->Child(0) == NULL ) { //&& node2->RightChild() == NULL ) { 01455 if ( node1->Child(0) ) { 01456 overlap = CheckSelfIntersectionsRecursively( node1->Child(0), node2 ); 01457 } 01458 if ( node1->Child(1) ) { 01459 overlap = CheckSelfIntersectionsRecursively( node1->Child(1), node2 ); 01460 } 01461 } 01462 else { 01463 if ( node2->Child(0) ) { 01464 overlap = node1->TestOverlapSphereWithSphere_NoPrimitiveTests( node2->Child(0) ); 01465 if ( overlap < DBL_MIN ) { 01466 if ( node1->Child(0) ) { 01467 overlap = CheckSelfIntersectionsRecursively( node1->Child(0), node2->Child(0) ); 01468 } 01469 if ( node1->Child(1) ) { 01470 overlap = CheckSelfIntersectionsRecursively( node1->Child(1), node2->Child(0) ); 01471 } 01472 } 01473 } 01474 if ( node2->Child(1) ) { 01475 overlap = node1->TestOverlapSphereWithSphere_NoPrimitiveTests( node2->Child(1) ); 01476 if ( overlap < DBL_MIN ) { 01477 if ( node1->Child(0) ) { 01478 overlap = CheckSelfIntersectionsRecursively( node1->Child(0), node2->Child(1) ); 01479 } 01480 if ( node1->Child(1) ) { 01481 overlap = CheckSelfIntersectionsRecursively( node1->Child(1), node2->Child(1) ); 01482 } 01483 } 01484 } 01485 } 01486 //------------------------------------------------------------ 01487 if ( node1->Child(0) == NULL && //node1->Child(1) == NULL && 01488 node2->Child(0) == NULL ) //&& node2->Child(1) == NULL ) 01489 { 01490 T distance; 01491 Vector3<T> U; 01492 int i = node1->GetID(); 01493 int j = node2->GetID(); 01494 01495 /* 01496 //-------------------------------------------------- 01497 // For Knot Tying (in intersection) 01498 if ( m_iLinkKnotGrp[i] >= 0 && (m_iLinkKnotGrp[i] == m_iLinkKnotGrp[j]) ) { 01499 return 0; 01500 } 01501 //*/ 01502 01503 //-------------------------------------------------- 01504 CGMath<T>::FindClosestDistanceBetweenTwoLineSegments( 01505 m_prVertex[i], m_prVertex[i+1], // Link# i 01506 m_prVertex[j], m_prVertex[j+1], // Link# j 01507 distance, U 01508 ); 01509 //* 01510 //-------------------------------------------------- 01511 // If collide, push the nodes apart GEOMETRICALLY 01512 if ( distance < LinkDiameter ) { 01513 //m_prVertex 01514 //std::cout << "Node#" << node1->GetID() << " intersects with " 01515 // << "Node#" << node2->GetID() << " by " << overlap; 01516 //std::cout << " with CONTACT: " << distance << " < " << LinkDiameter << "\n"; 01517 U *= m_tRadius - distance/static_cast<T>(2.0) + epsilon; 01518 01519 /* 01520 T length = U.Length(); 01521 if ( length > m_tRadius*4 ) { 01522 U /= length * m_tRadius*4; 01523 } 01524 //*/ 01525 01526 //U /= 2; 01527 /* 01528 m_prVertex[i] -= U; 01529 m_prVertex[i+1] -= U; 01530 m_prVertex[j] += U; 01531 m_prVertex[j+1] += U; 01532 //*/ 01533 01534 01535 #ifdef TAPs_STRAND_LOCK_SEGMENTS 01536 { 01537 //if ( !m_prIsLocked[i] && !m_prIsFixed[i] ) m_prVertex[i] -= U; 01538 //if ( !m_prIsLocked[j] && !m_prIsFixed[j] ) m_prVertex[j] += U; 01539 //if ( !m_prIsLocked[i+1] && !m_prIsFixed[i+1] ) m_prVertex[i+1] -= U; 01540 //if ( !m_prIsLocked[j+1] && !m_prIsFixed[j+1] ) m_prVertex[j+1] += U; 01541 if ( !m_prIsLocked[i] && !m_prIsLocked[i+1] ) { 01542 /* 01543 // Limit the link lneght, to prevent the non-stop move of point(s). 01544 // Here the length is limited to be not over a length threshold. 01545 T length = ( m_prVertex[i] - m_prVertex[i+1] ).Length(); 01546 if ( length < 2 * m_tLinkLength ) { 01547 if ( !m_prIsFixed[i] ) m_prVertex[i] -= U; 01548 if ( !m_prIsFixed[i+1] ) m_prVertex[i+1] -= U; 01549 } 01550 //*/ 01551 if ( !m_prIsFixed[i] && !m_prIsFixed[i+1] ) { 01552 m_prVertex[i] -= U; 01553 m_prVertex[i+1] -= U; 01554 } 01555 } 01556 if ( !m_prIsLocked[j] && !m_prIsLocked[j+1] ) { 01557 /* 01558 // Limit the link lneght, to prevent the non-stop move of point(s). 01559 // Here the length is limited to be not over a length threshold. 01560 T length = ( m_prVertex[j] - m_prVertex[j+1] ).Length(); 01561 if ( length < 2 * m_tLinkLength ) { 01562 if ( !m_prIsFixed[j] ) m_prVertex[j] += U; 01563 if ( !m_prIsFixed[j+1] ) m_prVertex[j+1] += U; 01564 } 01565 //*/ 01566 if ( !m_prIsFixed[j] && !m_prIsFixed[j+1] ) { 01567 m_prVertex[j] += U; 01568 m_prVertex[j+1] += U; 01569 } 01570 } 01571 } 01572 #else //TAPs_STRAND_LOCK_SEGMENTS 01573 { 01574 if ( !m_prIsFixed[i] ) m_prVertex[i] -= U; 01575 if ( !m_prIsFixed[j] ) m_prVertex[j] += U; 01576 if ( !m_prIsFixed[i+1] ) m_prVertex[i+1] -= U; 01577 if ( !m_prIsFixed[j+1] ) m_prVertex[j+1] += U; 01578 } 01579 #endif//TAPs_STRAND_LOCK_SEGMENTS 01580 01581 //m_prVertex[i] -= U; 01582 //m_prVertex[j] += U; 01583 //m_prVertex[i+1] -= U; 01584 //m_prVertex[j+1] += U; 01585 } 01586 01587 //*/ 01588 //-------------------------------------------------- 01589 // If collide, push the nodes apart PHYSICALLY (BASED ON FORCE) 01590 //Vector3<T> dir = ( node2->GetCenter() - node1->GetCenter() ); 01591 //distance = ( node1->GetRadius() + node2->GetRadius() ) - dir.Length(); 01592 //if ( distance > 0 ) { 01593 //* 01594 01595 /* 01596 //distance *= 2; 01597 if ( distance < LinkDiameter ) { 01598 Vector3<T> dir = ( node2->GetCenter() - node1->GetCenter() ); 01599 dir.Normalized(); 01600 Vector3<T> contactForce = m_tKContact1 * exp(m_tKContact2 * distance) * dir; 01601 m_prForce[i] -= contactForce; 01602 m_prForce[i+1] -= contactForce; 01603 m_prForce[j] += contactForce; 01604 m_prForce[j+1] += contactForce; 01605 //----------------------------------------- 01606 // Set WasIntersect Flags 01607 m_prWasIntersect[i] = m_prWasIntersect[j] = 1; 01608 } 01609 //*/ 01610 } 01611 } 01612 //---------------------------------------------------------------- 01613 return overlap; 01614 } 01615 //----------------------------------------------------------------------------- 01616 01617 #ifdef TAPs_STRAND_KNOT_RECOGNITION_BY_DOWKER_NOTATION 01618 //============================================================================= 01619 // START: Check Crossings for Knot Recognition by Dowker Notation 01620 //----------------------------------------------------------------------------- 01624 #ifdef TAPs_ALLOW_SETTING_PROJECTION_DIRECTION 01625 template <typename T> 01626 std::string ModelStrand<T>::GetKnotName ( Vector3<T> const & projectionDirection ) 01627 { 01628 #ifdef TAPs_STRAND_DEBUG 01629 special_debug_knotID = 01630 #endif//TAPs_STRAND_DEBUG 01631 CheckSelfCrossingForKnotRecognition( projectionDirection ); 01632 std::string knotName; 01633 DowkerNotationToKnotName( &knotName ); 01634 return knotName; 01635 } 01636 #else //TAPs_ALLOW_SETTING_PROJECTION_DIRECTION 01637 template <typename T> 01638 std::string ModelStrand<T>::GetKnotName () 01639 { 01640 #ifdef TAPs_STRAND_DEBUG 01641 special_debug_knotID = 01642 #endif//TAPs_STRAND_DEBUG 01643 CheckSelfCrossingForKnotRecognition(); 01644 std::string knotName; 01645 DowkerNotationToKnotName( &knotName ); 01646 return knotName; 01647 } 01648 #endif//TAPs_ALLOW_SETTING_PROJECTION_DIRECTION 01649 //----------------------------------------------------------------------------- 01650 01651 //----------------------------------------------------------------------------- 01652 01653 //----------------------------------------------------------------------------- 01655 template <typename T> 01656 void ModelStrand<T>::CheckSelfCrossingForKnotRecognition_zDir () 01657 { 01658 //---------------------------------------------------------------- 01659 // Reset 01660 for ( int i = 0; i < m_iMaxCrossingPairs; ++i ) m_iaDowkerNotation[i] = 0; 01661 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01662 m_crossings.clear(); 01663 01664 #ifdef DEBUG_TOO 01665 m_crossings_TOO.clear(); 01666 #endif//DEBUG_TOO 01667 01668 for ( int i = 0; i < m_iNoLinks; ++i ) m_iaCrossingCounters[i] = 0; 01669 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01670 for ( int i = 0; i < m_iNoLinks; ++i ) m_iaCrossingsForDowkerNotation[i] = 0; 01671 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01672 01673 //---------------------------------------------------------------- 01674 // Find Crossings 01675 CheckSelfCrossingsNextLevelRecursively_zDir( m_BVHTree->Root()->Child(0), 01676 m_BVHTree->Root()->Child(1) ); 01677 //---------------------------------------------------------------- 01678 // For Recording Dowker Notation 01679 std::vector<int> crosses; 01680 std::vector<int> crossesID; 01681 01682 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01683 01684 #ifdef DEBUG_TOO 01685 01686 std::list< IC_Crossing >::const_iterator it = m_crossings_TOO.begin(); 01687 while ( it != m_crossings_TOO.end() ) { 01688 01689 #else //DEBUG_TOO 01690 01691 std::list< IC_Crossing >::const_iterator it = m_crossings.begin(); 01692 while ( it != m_crossings.end() ) { 01693 01694 #endif//DEBUG_TOO 01695 01696 // crossesID records the node number that has another node cross over or under it. 01697 // crosses records the crossing identified by node number that crosses over the crossesID. 01698 // E.g. real cross# 1 2 3 4 5 6 01699 // crossesID: 30 31 32 74 77 79 01700 // crosses: -74 77 -79 30 -31 32 01701 // results in the Dowker notation below 01702 // Dowker#: (1,4) (3,6) (5,2) 01703 // which is a half knot 01704 crossesID.push_back( (*it).id ); 01705 crosses.push_back( (*it).number ); 01706 ++it; 01707 } 01708 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01709 for ( int i = 0; i < m_iNoLinks; ++i ) { 01710 if ( m_iaCrossingsForDowkerNotation[i] != 0 ) { 01711 // crossesID records the node number that has another node cross over or under it. 01712 // crosses records the crossing identified by node number that crosses over the crossesID. 01713 // E.g. real cross# 1 2 3 4 5 6 01714 // crossesID: 30 31 32 74 77 79 01715 // crosses: -74 77 -79 30 -31 32 01716 // results in the Dowker notation below 01717 // Dowker#: (1,4) (3,6) (5,2) 01718 // which is a half knot 01719 crossesID.push_back( i+1 ); 01720 crosses.push_back( m_iaCrossingsForDowkerNotation[i] ); 01721 } 01722 } 01723 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01724 01725 int numOfCrosses = static_cast<int>( crosses.size() ); 01726 if ( numOfCrosses == 0 ) { // Not a knot 01727 m_iKnotStartPt = m_iKnotEndPt = -1; 01728 m_iNumCrossingPairs = 0; 01729 } 01730 else if ( numOfCrosses % 2 == 0 ) { 01731 m_iNumCrossingPairs = numOfCrosses/2; 01732 assert( m_iNumCrossingPairs <= m_iMaxCrossingPairs ); 01733 int idx = 0; 01734 for ( int i = 0, odd = 1; i < numOfCrosses; i+=2, odd+=2 ) { 01735 for ( int j = 1, even = 2; j < numOfCrosses; j+=2, even+=2 ) { 01736 if ( crossesID[i] == abs( crosses[j] ) ) { 01737 //iaDowkerNotation[ idx++ ] = odd; 01738 if ( crosses[j] < 0 ) 01739 m_iaDowkerNotation[ idx++ ] = -even; 01740 else 01741 m_iaDowkerNotation[ idx++ ] = even; 01742 } 01743 } 01744 } 01745 01747 m_iKnotStartPt = crossesID[0]; 01748 m_iKnotEndPt = crossesID[numOfCrosses-1]; 01749 } 01750 else { // Not a knot 01751 m_iKnotStartPt = m_iKnotEndPt = -1; 01752 m_iNumCrossingPairs = numOfCrosses/2; 01753 } 01754 01755 #ifdef TAPs_STRAND_DEBUG 01756 01757 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01758 /* 01759 { 01760 std::cout << "NUMs: "; 01761 std::list< IC_Crossing >::const_iterator it = m_crossings.begin(); 01762 while ( it != m_crossings.end() ) { 01763 std::cout << "\t" << (*it).number; 01764 ++it; 01765 } 01766 std::cout << "\n"; 01767 std::cout << "IDs: "; 01768 it = m_crossings.begin(); 01769 while ( it != m_crossings.end() ) { 01770 std::cout << "\t" << (*it).id; 01771 ++it; 01772 } 01773 std::cout << "\n"; 01774 } 01775 //*/ 01776 01777 /* 01778 #ifdef DEBUG_TOO 01779 { 01780 std::cout << "NUMs: "; 01781 std::list< IC_Crossing >::const_iterator it = m_crossings_TOO.begin(); 01782 while ( it != m_crossings_TOO.end() ) { 01783 std::cout << "\t" << (*it).number; 01784 ++it; 01785 } 01786 std::cout << "\n"; 01787 std::cout << "IDs: "; 01788 it = m_crossings_TOO.begin(); 01789 while ( it != m_crossings_TOO.end() ) { 01790 std::cout << "\t" << (*it).id; 01791 ++it; 01792 } 01793 std::cout << "\n"; 01794 } 01795 #endif//DEBUG_TOO 01796 //*/ 01797 01798 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01799 01800 debug_crosses = crosses; 01801 debug_crossesID = crossesID; 01802 std::cout << Debug_Str(); 01803 #endif//TAPs_STRAND_DEBUG 01804 01805 } 01806 //----------------------------------------------------------------------------- 01807 01808 //----------------------------------------------------------------------------- 01810 template <typename T> 01811 void ModelStrand<T>::CheckSelfCrossingForKnotRecognition_yDir () 01812 { 01813 //---------------------------------------------------------------- 01814 // Reset 01815 for ( int i = 0; i < m_iMaxCrossingPairs; ++i ) m_iaDowkerNotation[i] = 0; 01816 for ( int i = 0; i < m_iNoLinks; ++i ) m_iaCrossingsForDowkerNotation[i] = 0; 01817 //---------------------------------------------------------------- 01818 // Find Crossings 01819 CheckSelfCrossingsNextLevelRecursively_yDir( m_BVHTree->Root()->Child(0), 01820 m_BVHTree->Root()->Child(1), 01821 m_iaCrossingsForDowkerNotation ); 01822 //---------------------------------------------------------------- 01823 // Record Dowker Notation 01824 std::vector<int> crosses; 01825 std::vector<int> crossesID; 01826 for ( int i = 0; i < m_iNoLinks; ++i ) { 01827 if ( m_iaCrossingsForDowkerNotation[i] != 0 ) { 01828 crosses.push_back( m_iaCrossingsForDowkerNotation[i] ); 01829 crossesID.push_back( i+1 ); 01830 } 01831 } 01832 int numOfCrosses = static_cast<int>( crosses.size() ); 01833 if ( numOfCrosses == 0 ) { // Not a knot 01834 m_iKnotStartPt = m_iKnotEndPt = -1; 01835 m_iNumCrossingPairs = 0; 01836 } 01837 else if ( numOfCrosses % 2 == 0 ) { 01838 m_iNumCrossingPairs = numOfCrosses/2; 01839 assert( m_iNumCrossingPairs <= m_iMaxCrossingPairs ); 01840 int idx = 0; 01841 for ( int i = 0, odd = 1; i < numOfCrosses; i+=2, odd+=2 ) { 01842 for ( int j = 1, even = 2; j < numOfCrosses; j+=2, even+=2 ) { 01843 if ( crossesID[i] == abs( crosses[j] ) ) { 01844 //iaDowkerNotation[ idx++ ] = odd; 01845 if ( crosses[j] < 0 ) 01846 m_iaDowkerNotation[ idx++ ] = -even; 01847 else 01848 m_iaDowkerNotation[ idx++ ] = even; 01849 } 01850 } 01851 } 01852 01854 m_iKnotStartPt = crossesID[0]; 01855 m_iKnotEndPt = crossesID[numOfCrosses-1]; 01856 } 01857 else { // Not a knot 01858 m_iKnotStartPt = m_iKnotEndPt = -1; 01859 m_iNumCrossingPairs = numOfCrosses/2; 01860 } 01861 } 01862 //----------------------------------------------------------------------------- 01863 01864 //----------------------------------------------------------------------------- 01866 template <typename T> 01867 void ModelStrand<T>::CheckSelfCrossingForKnotRecognition_xDir () 01868 { 01869 //---------------------------------------------------------------- 01870 // Reset 01871 for ( int i = 0; i < m_iMaxCrossingPairs; ++i ) m_iaDowkerNotation[i] = 0; 01872 for ( int i = 0; i < m_iNoLinks; ++i ) m_iaCrossingsForDowkerNotation[i] = 0; 01873 //---------------------------------------------------------------- 01874 // Find Crossings 01875 CheckSelfCrossingsNextLevelRecursively_xDir( m_BVHTree->Root()->Child(0), 01876 m_BVHTree->Root()->Child(1), 01877 m_iaCrossingsForDowkerNotation ); 01878 //---------------------------------------------------------------- 01879 // Record Dowker Notation 01880 std::vector<int> crosses; 01881 std::vector<int> crossesID; 01882 for ( int i = 0; i < m_iNoLinks; ++i ) { 01883 if ( m_iaCrossingsForDowkerNotation[i] != 0 ) { 01884 crosses.push_back( m_iaCrossingsForDowkerNotation[i] ); 01885 crossesID.push_back( i+1 ); 01886 } 01887 } 01888 int numOfCrosses = static_cast<int>( crosses.size() ); 01889 if ( numOfCrosses == 0 ) { // Not a knot 01890 m_iKnotStartPt = m_iKnotEndPt = -1; 01891 m_iNumCrossingPairs = 0; 01892 } 01893 else if ( numOfCrosses % 2 == 0 ) { 01894 m_iNumCrossingPairs = numOfCrosses/2; 01895 assert( m_iNumCrossingPairs <= m_iMaxCrossingPairs ); 01896 int idx = 0; 01897 for ( int i = 0, odd = 1; i < numOfCrosses; i+=2, odd+=2 ) { 01898 for ( int j = 1, even = 2; j < numOfCrosses; j+=2, even+=2 ) { 01899 if ( crossesID[i] == abs( crosses[j] ) ) { 01900 //iaDowkerNotation[ idx++ ] = odd; 01901 if ( crosses[j] < 0 ) 01902 m_iaDowkerNotation[ idx++ ] = -even; 01903 else 01904 m_iaDowkerNotation[ idx++ ] = even; 01905 } 01906 } 01907 } 01908 01910 m_iKnotStartPt = crossesID[0]; 01911 m_iKnotEndPt = crossesID[numOfCrosses-1]; 01912 } 01913 else { // Not a knot 01914 m_iKnotStartPt = m_iKnotEndPt = -1; 01915 m_iNumCrossingPairs = numOfCrosses/2; 01916 } 01917 } 01918 //----------------------------------------------------------------------------- 01919 01920 #ifdef TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 01921 //----------------------------------------------------------------------------- 01922 // CreateDataSpaceForKnotRecognitionByDowkerNotation 01923 template <typename T> 01924 bool ModelStrand<T>::CheckClumped ( int startPt, int endPt, T sphereRadius ) 01925 { 01926 // Return false if the clump is less then 6 links. 01927 if ( endPt - startPt < 5 ) { 01928 m_bIsClumped = false; 01929 return m_bIsClumped; 01930 } 01931 01932 #ifdef TAPs_STRAND_LOCK_SEGMENTS 01933 // Determine the sphere center 01934 Vector3<T> avgPt( 0,0,0 ); 01935 int count = 0; 01936 for ( int i = startPt; i <= endPt; ++i ) { 01937 if ( !m_prIsLocked[i] ) { // skip locked point 01938 avgPt += m_prVertex[i]; 01939 ++count; 01940 } 01941 } 01942 avgPt /= count; 01943 01944 // Return true if all points are within the sphere, else return false. 01945 for ( int i = startPt; i <= endPt; ++i ) { 01946 if ( !m_prIsLocked[i] ) { // skip locked point 01947 T length = ( avgPt - m_prVertex[i] ).Length(); 01948 if ( length > sphereRadius ) { 01949 m_bIsClumped = false; 01950 return m_bIsClumped; 01951 } 01952 } 01953 } 01954 #else //TAPs_STRAND_LOCK_SEGMENTS 01955 // Determine the sphere center 01956 Vector3<T> avgPt( m_prVertex[startPt] ); 01957 for ( int i = startPt+1; i <= endPt; ++i ) { 01958 avgPt += m_prVertex[i]; 01959 } 01960 avgPt /= ( endPt - startPt + 1 ); 01961 01962 // Return true if all points are within the sphere, else return false. 01963 for ( int i = startPt; i <= endPt; ++i ) { 01964 T length = ( avgPt - m_prVertex[i] ).Length(); 01965 if ( length > sphereRadius ) { 01966 m_bIsClumped = false; 01967 return m_bIsClumped; 01968 } 01969 } 01970 #endif//TAPs_STRAND_LOCK_SEGMENTS 01971 01972 m_bIsClumped = true; 01973 return m_bIsClumped; 01974 } 01975 #endif//TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 01976 //----------------------------------------------------------------------------- 01977 01978 //----------------------------------------------------------------------------- 01979 // CreateDataSpaceForKnotRecognitionByDowkerNotation 01980 template <typename T> 01981 void ModelStrand<T>::CreateDataSpaceForKnotRecognitionByDowkerNotation () 01982 { 01983 //m_ucNumKnots = 0; //! Init number of knots on the strand to zero 01984 m_iKnotStartPt = m_iKnotEndPt = -1; 01985 //---------------------------------------------------------------- 01986 m_iMaxCrossingPairs = m_iNoLinks/2; 01987 m_iNumCrossingPairs = 0; 01988 //---------------------------------------------------------------- 01989 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 01990 if ( ( m_iaCrossingCounters = new int[ m_iNoLinks ] ) == NULL ) { 01991 #ifdef TAPs_ENABLE_DEBUG 01992 std::cerr << "ERROR => ModelStrand Constructor:" 01993 << " Cannot allocate memory for knot recognition by Dowker notation!" 01994 << std::endl; 01995 #endif 01996 delete this; 01997 return; 01998 } 01999 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02000 if ( ( m_iaCrossingsForDowkerNotation = new int[ m_iNoLinks ] ) == NULL ) { 02001 #ifdef TAPs_ENABLE_DEBUG 02002 std::cerr << "ERROR => ModelStrand Constructor:" 02003 << " Cannot allocate memory for knot recognition by Dowker notation!" 02004 << std::endl; 02005 #endif 02006 delete this; 02007 return; 02008 } 02009 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02010 //---------------------------------------------------------------- 02011 if ( ( m_iaDowkerNotation = new int[ m_iMaxCrossingPairs ] ) == NULL ) { 02012 #ifdef TAPs_ENABLE_DEBUG 02013 std::cerr << "ERROR => ModelStrand Constructor:" 02014 << " Cannot allocate memory for knot recognition by Dowker notation!" 02015 << std::endl; 02016 #endif 02017 delete this; 02018 return; 02019 } 02020 } 02021 //----------------------------------------------------------------------------- 02022 // DeleteDataSpaceForKnotRecognitionByDowkerNotation 02023 template <typename T> 02024 void ModelStrand<T>::DeleteDataSpaceForKnotRecognitionByDowkerNotation () 02025 { 02026 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02027 if ( m_iaCrossingCounters ) { 02028 delete [] m_iaCrossingCounters; 02029 m_iaCrossingCounters = NULL; 02030 } 02031 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02032 if ( m_iaCrossingsForDowkerNotation ) { 02033 delete [] m_iaCrossingsForDowkerNotation; 02034 m_iaCrossingsForDowkerNotation = NULL; 02035 } 02036 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02037 02038 if ( m_iaDowkerNotation ) { 02039 delete [] m_iaDowkerNotation; 02040 m_iaDowkerNotation = NULL; 02041 } 02042 } 02043 //----------------------------------------------------------------------------- 02044 02045 //============================================================================= 02046 // START: Fns for CheckSelfCrossingForKnotRecognition_zDir function 02047 //----------------------------------------------------------------------------- 02048 // CheckSelfCrossingsNextLevelRecursively 02049 // Assume no intersections between immediate adjacent links 02050 // Assume a BVH node either has both children or none, therefore 02051 // checking either it has a left or right child is enough to determine 02052 // whether it is a leaf node or not. 02053 template <typename T> 02054 void ModelStrand<T>::CheckSelfCrossingsNextLevelRecursively_zDir ( 02055 BVHNode<T> * node1, 02056 BVHNode<T> * node2 02057 ) 02058 { 02059 CheckSelfCrossingsRecursively_zDir( node1, node2 ); 02060 if ( node1->Child(0) ) 02061 CheckSelfCrossingsNextLevelRecursively_zDir( node1->Child(0), node1->Child(1) ); 02062 if ( node2->Child(0) ) 02063 CheckSelfCrossingsNextLevelRecursively_zDir( node2->Child(0), node2->Child(1) ); 02064 } 02065 //----------------------------------------------------------------------------- 02066 // CheckSelfCrossingsRecursively 02067 // Assume no intersections between immediate adjacent links 02068 // Use the fact that the ids of sphere bvh leaf nodes are the same as 02069 // the link id and 02070 template <typename T> 02071 T ModelStrand<T>::CheckSelfCrossingsRecursively_zDir ( 02072 BVHNode<T> * node1, 02073 BVHNode<T> * node2 02074 ) 02075 { 02076 static T LinkDiameter = static_cast<T>(2.0) * m_tRadius; 02077 static T epsilon = m_tRadius * static_cast<T>(0.05); // for collision response 02078 //--------------------------------------------------------------- 02079 if ( !node1->Child(0) && !node2->Child(0) && 02080 ( abs(node1->GetID() - node2->GetID()) == 1 ) ) 02081 { 02082 return DBL_MAX; 02083 } 02084 //--------------------------------------------------------------- 02085 T overlap = TestOverlapCircle_zDir( node1, node2 ); 02086 //--------------------------------------------------------------- 02087 if ( overlap < DBL_MIN ) { 02088 if ( node2->Child(0) == NULL ) { //&& node2->RightChild() == NULL ) { 02089 if ( node1->Child(0) ) { 02090 overlap = CheckSelfCrossingsRecursively_zDir( node1->Child(0), node2 ); 02091 } 02092 if ( node1->Child(1) ) { 02093 overlap = CheckSelfCrossingsRecursively_zDir( node1->Child(1), node2 ); 02094 } 02095 } 02096 else { 02097 if ( node2->Child(0) ) { 02098 overlap = TestOverlapCircle_zDir( node1, node2->Child(0) ); 02099 if ( overlap < DBL_MIN ) { 02100 if ( node1->Child(0) ) { 02101 overlap = CheckSelfCrossingsRecursively_zDir( node1->Child(0), node2->Child(0) ); 02102 } 02103 if ( node1->Child(1) ) { 02104 overlap = CheckSelfCrossingsRecursively_zDir( node1->Child(1), node2->Child(0) ); 02105 } 02106 } 02107 } 02108 if ( node2->Child(1) ) { 02109 overlap = TestOverlapCircle_zDir( node1, node2->Child(1) ); 02110 if ( overlap < DBL_MIN ) { 02111 if ( node1->Child(0) ) { 02112 overlap = CheckSelfCrossingsRecursively_zDir( node1->Child(0), node2->Child(1) ); 02113 } 02114 if ( node1->Child(1) ) { 02115 overlap = CheckSelfCrossingsRecursively_zDir( node1->Child(1), node2->Child(1) ); 02116 } 02117 } 02118 } 02119 } 02120 //----------------------------------------------------------- 02121 if ( node1->Child(0) == NULL && //node1->Child(1) == NULL && 02122 node2->Child(0) == NULL ) //&& node2->Child(1) == NULL ) 02123 { 02124 CheckCrossings_zDir( node1, node2 ); 02125 } 02126 } 02127 //--------------------------------------------------------------- 02128 return overlap; 02129 } 02130 //----------------------------------------------------------------------------- 02131 template <typename T> 02132 T ModelStrand<T>::TestOverlapCircle_zDir ( 02133 BVHNode<T> * node1, BVHNode<T> * node2 ) 02134 { 02135 Vector3<T> C1 = node1->GetCenter(); 02136 Vector3<T> C2 = node2->GetCenter(); 02137 C1.SetZ( 0 ); 02138 C2.SetZ( 0 ); 02139 return (C1 - C2).Length() - ( node1->GetRadius() + node2->GetRadius() ); 02140 } 02141 //----------------------------------------------------------------------------- 02142 template <typename T> 02143 void ModelStrand<T>::CheckCrossings_zDir ( 02144 BVHNode<T> * node1, BVHNode<T> * node2 ) 02145 { 02146 int i = node1->GetID(); 02147 int j = node2->GetID(); 02148 02149 // Skip if a node is locked 02150 #ifdef TAPs_STRAND_LOCK_SEGMENTS 02151 if ( m_prIsLocked[i] ) return; 02152 if ( m_prIsLocked[j] ) return; 02153 #endif//TAPs_STRAND_LOCK_SEGMENTS 02154 02155 // Link# i 02156 Vector3<T> p1 = m_prVertex[i]; 02157 Vector3<T> p2 = m_prVertex[i+1]; 02158 // Link# j 02159 Vector3<T> q1 = m_prVertex[j]; 02160 Vector3<T> q2 = m_prVertex[j+1]; 02161 02162 // Project in z-direction 02163 p1.SetZ( 0 ); 02164 p2.SetZ( 0 ); 02165 q1.SetZ( 0 ); 02166 q2.SetZ( 0 ); 02167 02168 bool isTouched; 02169 T pt, qt; // parameter for the 1st & 2nd line 02170 // where intersection point = p1 + pt(p2-p1) 02171 // where intersection point = q1 + qt(q2-q1) 02172 CGMath<T>::FindIntersectionLineSegmentLineSegment( 02173 p1, p2, q1, q2, // I/P 02174 pt, qt, // O/P 02175 isTouched // O/P 02176 ); 02177 if ( 0 <= pt && pt <= 1 && 0 <= qt && qt <= 1 ) { 02178 Vector3<T> P = m_prVertex[i] + pt*( m_prVertex[i+1] - m_prVertex[i] ); 02179 Vector3<T> Q = m_prVertex[j] + qt*( m_prVertex[j+1] - m_prVertex[j] ); 02180 02181 // i+1 and j+1 are for making the link# to be one-based instead of zero-based 02182 if ( P[2] > Q[2] ) { 02183 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02184 02185 #ifdef DEBUG_TOO 02186 int a = i*10 + m_iaCrossingCounters[i]++; 02187 int b = j*10 + m_iaCrossingCounters[j]++; 02188 InsertToList_TOO( -b, a ); 02189 InsertToList_TOO( a, b ); 02190 #endif//DEBUG_TOO 02191 02192 InsertToList( -(j), i ); 02193 InsertToList( +(i), j ); 02194 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02195 m_iaCrossingsForDowkerNotation[i] = -(j+1); // the link i is above the link j 02196 m_iaCrossingsForDowkerNotation[j] = +(i+1); // the link j is below the link i 02197 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02198 } 02199 else { 02200 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02201 02202 #ifdef DEBUG_TOO 02203 int a = i*10 + m_iaCrossingCounters[i]++; 02204 int b = j*10 + m_iaCrossingCounters[j]++; 02205 InsertToList_TOO( b, a ); 02206 InsertToList_TOO( -a, b ); 02207 #endif//DEBUG_TOO 02208 02209 InsertToList( +(j), i ); 02210 InsertToList( -(i), j ); 02211 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02212 m_iaCrossingsForDowkerNotation[i] = +(j+1); // the link j is above the link i 02213 m_iaCrossingsForDowkerNotation[j] = -(i+1); // the link i is below the link j 02214 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 02215 } 02216 } 02217 } 02218 //----------------------------------------------------------------------------- 02219 // END: Fns for CheckSelfCrossingForKnotRecognition_zDir function 02220 //============================================================================= 02221 02222 02223 02224 //============================================================================= 02225 // START: Fns for CheckSelfCrossingForKnotRecognition_yDir function 02226 //----------------------------------------------------------------------------- 02227 // CheckSelfCrossingsNextLevelRecursively 02228 // Assume no intersections between immediate adjacent links 02229 // Assume a BVH node either has both children or none, therefore 02230 // checking either it has a left or right child is enough to determine 02231 // whether it is a leaf node or not. 02232 template <typename T> 02233 void ModelStrand<T>::CheckSelfCrossingsNextLevelRecursively_yDir ( 02234 BVHNode<T> * node1, 02235 BVHNode<T> * node2 02236 ) 02237 { 02238 CheckSelfCrossingsRecursively_yDir( node1, node2 ); 02239 if ( node1->Child(0) ) 02240 CheckSelfCrossingsNextLevelRecursively_yDir( node1->Child(0), node1->Child(1) ); 02241 if ( node2->Child(0) ) 02242 CheckSelfCrossingsNextLevelRecursively_yDir( node2->Child(0), node2->Child(1) ); 02243 } 02244 //----------------------------------------------------------------------------- 02245 // CheckSelfCrossingsRecursively 02246 // Assume no intersections between immediate adjacent links 02247 // Use the fact that the ids of sphere bvh leaf nodes are the same as 02248 // the link id and 02249 template <typename T> 02250 T ModelStrand<T>::CheckSelfCrossingsRecursively_yDir ( 02251 BVHNode<T> * node1, 02252 BVHNode<T> * node2 02253 ) 02254 { 02255 static T LinkDiameter = static_cast<T>(2.0) * m_tRadius; 02256 static T epsilon = m_tRadius * static_cast<T>(0.05); // for collision response 02257 //--------------------------------------------------------------- 02258 if ( !node1->Child(0) && !node2->Child(0) && 02259 ( abs(node1->GetID() - node2->GetID()) == 1 ) ) 02260 { 02261 return DBL_MAX; 02262 } 02263 //--------------------------------------------------------------- 02264 T overlap = TestOverlapCircle_yDir( node1, node2 ); 02265 //--------------------------------------------------------------- 02266 if ( overlap < DBL_MIN ) { 02267 if ( node2->Child(0) == NULL ) { //&& node2->RightChild() == NULL ) { 02268 if ( node1->Child(0) ) { 02269 overlap = CheckSelfCrossingsRecursively_yDir( node1->Child(0), node2 ); 02270 } 02271 if ( node1->Child(1) ) { 02272 overlap = CheckSelfCrossingsRecursively_yDir( node1->Child(1), node2 ); 02273 } 02274 } 02275 else { 02276 if ( node2->Child(0) ) { 02277 overlap = TestOverlapCircle_yDir( node1, node2->Child(0) ); 02278 if ( overlap < DBL_MIN ) { 02279 if ( node1->Child(0) ) { 02280 overlap = CheckSelfCrossingsRecursively_yDir( node1->Child(0), node2->Child(0) ); 02281 } 02282 if ( node1->Child(1) ) { 02283 overlap = CheckSelfCrossingsRecursively_yDir( node1->Child(1), node2->Child(0) ); 02284 } 02285 } 02286 } 02287 if ( node2->Child(1) ) { 02288 overlap = TestOverlapCircle_yDir( node1, node2->Child(1) ); 02289 if ( overlap < DBL_MIN ) { 02290 if ( node1->Child(0) ) { 02291 overlap = CheckSelfCrossingsRecursively_yDir( node1->Child(0), node2->Child(1) ); 02292 } 02293 if ( node1->Child(1) ) { 02294 overlap = CheckSelfCrossingsRecursively_yDir( node1->Child(1), node2->Child(1) ); 02295 } 02296 } 02297 } 02298 } 02299 //----------------------------------------------------------- 02300 if ( node1->Child(0) == NULL && //node1->Child(1) == NULL && 02301 node2->Child(0) == NULL ) //&& node2->Child(1) == NULL ) 02302 { 02303 CheckCrossings_yDir( node1, node2 ); 02304 } 02305 } 02306 //--------------------------------------------------------------- 02307 return overlap; 02308 } 02309 //----------------------------------------------------------------------------- 02310 template <typename T> 02311 T ModelStrand<T>::TestOverlapCircle_yDir ( 02312 BVHNode<T> * node1, BVHNode<T> * node2 ) 02313 { 02314 Vector3<T> C1 = node1->GetCenter(); 02315 Vector3<T> C2 = node2->GetCenter(); 02316 C1.SetY( 0 ); 02317 C2.SetY( 0 ); 02318 return (C1 - C2).Length() - ( node1->GetRadius() + node2->GetRadius() ); 02319 } 02320 //----------------------------------------------------------------------------- 02321 template <typename T> 02322 void ModelStrand<T>::CheckCrossings_yDir ( 02323 BVHNode<T> * node1, BVHNode<T> * node2 ) 02324 { 02325 int i = node1->GetID(); 02326 int j = node2->GetID(); 02327 02328 // Skip if a node is locked 02329 #ifdef TAPs_STRAND_LOCK_SEGMENTS 02330 if ( m_prIsLocked[i] ) return; 02331 if ( m_prIsLocked[j] ) return; 02332 #endif//TAPs_STRAND_LOCK_SEGMENTS 02333 02334 // Link# i 02335 Vector3<T> p1 = m_prVertex[i]; 02336 Vector3<T> p2 = m_prVertex[i+1]; 02337 // Link# j 02338 Vector3<T> q1 = m_prVertex[j]; 02339 Vector3<T> q2 = m_prVertex[j+1]; 02340 02341 // Project in z-direction 02342 p1.SetY( 0 ); 02343 p2.SetY( 0 ); 02344 q1.SetY( 0 ); 02345 q2.SetY( 0 ); 02346 02347 bool isTouched; 02348 T pt, qt; // parameter for the 1st & 2nd line 02349 // where intersection point = p1 + pt(p2-p1) 02350 // where intersection point = q1 + qt(q2-q1) 02351 CGMath<T>::FindIntersectionLineSegmentLineSegment( 02352 p1, p2, q1, q2, // I/P 02353 pt, qt, // O/P 02354 isTouched // O/P 02355 ); 02356 if ( 0 <= pt && pt <= 1 && 0 <= qt && qt <= 1 ) { 02357 Vector3<T> P = m_prVertex[i] + pt*( m_prVertex[i+1] - m_prVertex[i] ); 02358 Vector3<T> Q = m_prVertex[j] + qt*( m_prVertex[j+1] - m_prVertex[j] ); 02359 02360 // i+1 and j+1 are for making the link# to be one-based instead of zero-based 02361 if ( P[2] > Q[2] ) { 02362 m_iaCrossingsForDowkerNotation[i] = -(j+1); // the link i is above the link j 02363 m_iaCrossingsForDowkerNotation[j] = +(i+1); // the link j is below the link i 02364 } 02365 else { 02366 m_iaCrossingsForDowkerNotation[i] = +(j+1); // the link j is above the link i 02367 m_iaCrossingsForDowkerNotation[j] = -(i+1); // the link i is below the link j 02368 } 02369 } 02370 } 02371 //----------------------------------------------------------------------------- 02372 // END: Fns for CheckSelfCrossingForKnotRecognition_yDir function 02373 //============================================================================= 02374 02375 02376 02377 //============================================================================= 02378 // START: Fns for CheckSelfCrossingForKnotRecognition_xDir function 02379 //----------------------------------------------------------------------------- 02380 // CheckSelfCrossingsNextLevelRecursively 02381 // Assume no intersections between immediate adjacent links 02382 // Assume a BVH node either has both children or none, therefore 02383 // checking either it has a left or right child is enough to determine 02384 // whether it is a leaf node or not. 02385 template <typename T> 02386 void ModelStrand<T>::CheckSelfCrossingsNextLevelRecursively_xDir ( 02387 BVHNode<T> * node1, 02388 BVHNode<T> * node2 02389 ) 02390 { 02391 CheckSelfCrossingsRecursively_xDir( node1, node2 ); 02392 if ( node1->Child(0) ) 02393 CheckSelfCrossingsNextLevelRecursively_xDir( node1->Child(0), node1->Child(1) ); 02394 if ( node2->Child(0) ) 02395 CheckSelfCrossingsNextLevelRecursively_xDir( node2->Child(0), node2->Child(1) ); 02396 } 02397 //----------------------------------------------------------------------------- 02398 // CheckSelfCrossingsRecursively 02399 // Assume no intersections between immediate adjacent links 02400 // Use the fact that the ids of sphere bvh leaf nodes are the same as 02401 // the link id and 02402 template <typename T> 02403 T ModelStrand<T>::CheckSelfCrossingsRecursively_xDir ( 02404 BVHNode<T> * node1, 02405 BVHNode<T> * node2 02406 ) 02407 { 02408 static T LinkDiameter = static_cast<T>(2.0) * m_tRadius; 02409 static T epsilon = m_tRadius * static_cast<T>(0.05); // for collision response 02410 //--------------------------------------------------------------- 02411 if ( !node1->Child(0) && !node2->Child(0) && 02412 ( abs(node1->GetID() - node2->GetID()) == 1 ) ) 02413 { 02414 return DBL_MAX; 02415 } 02416 //--------------------------------------------------------------- 02417 T overlap = TestOverlapCircle_xDir( node1, node2 ); 02418 //--------------------------------------------------------------- 02419 if ( overlap < DBL_MIN ) { 02420 if ( node2->Child(0) == NULL ) { //&& node2->RightChild() == NULL ) { 02421 if ( node1->Child(0) ) { 02422 overlap = CheckSelfCrossingsRecursively_xDir( node1->Child(0), node2 ); 02423 } 02424 if ( node1->Child(1) ) { 02425 overlap = CheckSelfCrossingsRecursively_xDir( node1->Child(1), node2 ); 02426 } 02427 } 02428 else { 02429 if ( node2->Child(0) ) { 02430 overlap = TestOverlapCircle_xDir( node1, node2->Child(0) ); 02431 if ( overlap < DBL_MIN ) { 02432 if ( node1->Child(0) ) { 02433 overlap = CheckSelfCrossingsRecursively_xDir( node1->Child(0), node2->Child(0) ); 02434 } 02435 if ( node1->Child(1) ) { 02436 overlap = CheckSelfCrossingsRecursively_xDir( node1->Child(1), node2->Child(0) ); 02437 } 02438 } 02439 } 02440 if ( node2->Child(1) ) { 02441 overlap = TestOverlapCircle_xDir( node1, node2->Child(1) ); 02442 if ( overlap < DBL_MIN ) { 02443 if ( node1->Child(0) ) { 02444 overlap = CheckSelfCrossingsRecursively_xDir( node1->Child(0), node2->Child(1) ); 02445 } 02446 if ( node1->Child(1) ) { 02447 overlap = CheckSelfCrossingsRecursively_xDir( node1->Child(1), node2->Child(1) ); 02448 } 02449 } 02450 } 02451 } 02452 //----------------------------------------------------------- 02453 if ( node1->Child(0) == NULL && //node1->Child(1) == NULL && 02454 node2->Child(0) == NULL ) //&& node2->Child(1) == NULL ) 02455 { 02456 CheckCrossings_xDir( node1, node2 ); 02457 } 02458 } 02459 //--------------------------------------------------------------- 02460 return overlap; 02461 } 02462 //----------------------------------------------------------------------------- 02463 template <typename T> 02464 T ModelStrand<T>::TestOverlapCircle_xDir ( 02465 BVHNode<T> * node1, BVHNode<T> * node2 ) 02466 { 02467 Vector3<T> C1 = node1->GetCenter(); 02468 Vector3<T> C2 = node2->GetCenter(); 02469 C1.SetX( 0 ); 02470 C2.SetX( 0 ); 02471 return (C1 - C2).Length() - ( node1->GetRadius() + node2->GetRadius() ); 02472 } 02473 //----------------------------------------------------------------------------- 02474 template <typename T> 02475 void ModelStrand<T>::CheckCrossings_xDir ( 02476 BVHNode<T> * node1, BVHNode<T> * node2 ) 02477 { 02478 int i = node1->GetID(); 02479 int j = node2->GetID(); 02480 02481 // Skip if a node is locked 02482 #ifdef TAPs_STRAND_LOCK_SEGMENTS 02483 if ( m_prIsLocked[i] ) return; 02484 if ( m_prIsLocked[j] ) return; 02485 #endif//TAPs_STRAND_LOCK_SEGMENTS 02486 02487 // Link# i 02488 Vector3<T> p1 = m_prVertex[i]; 02489 Vector3<T> p2 = m_prVertex[i+1]; 02490 // Link# j 02491 Vector3<T> q1 = m_prVertex[j]; 02492 Vector3<T> q2 = m_prVertex[j+1]; 02493 02494 // Project in z-direction 02495 p1.SetX( 0 ); 02496 p2.SetX( 0 ); 02497 q1.SetX( 0 ); 02498 q2.SetX( 0 ); 02499 02500 bool isTouched; 02501 T pt, qt; // parameter for the 1st & 2nd line 02502 // where intersection point = p1 + pt(p2-p1) 02503 // where intersection point = q1 + qt(q2-q1) 02504 CGMath<T>::FindIntersectionLineSegmentLineSegment( 02505 p1, p2, q1, q2, // I/P 02506 pt, qt, // O/P 02507 isTouched // O/P 02508 ); 02509 if ( 0 <= pt && pt <= 1 && 0 <= qt && qt <= 1 ) { 02510 Vector3<T> P = m_prVertex[i] + pt*( m_prVertex[i+1] - m_prVertex[i] ); 02511 Vector3<T> Q = m_prVertex[j] + qt*( m_prVertex[j+1] - m_prVertex[j] ); 02512 02513 // i+1 and j+1 are for making the link# to be one-based instead of zero-based 02514 if ( P[2] > Q[2] ) { 02515 m_iaCrossingsForDowkerNotation[i] = -(j+1); // the link i is above the link j 02516 m_iaCrossingsForDowkerNotation[j] = +(i+1); // the link j is below the link i 02517 } 02518 else { 02519 m_iaCrossingsForDowkerNotation[i] = +(j+1); // the link j is above the link i 02520 m_iaCrossingsForDowkerNotation[j] = -(i+1); // the link i is below the link j 02521 } 02522 } 02523 } 02524 //----------------------------------------------------------------------------- 02525 // END: Fns for CheckSelfCrossingForKnotRecognition_xDir function 02526 //============================================================================= 02527 02528 02529 02530 //----------------------------------------------------------------------------- 02531 template <typename T> 02532 int ModelStrand<T>::DowkerNotationToKnotName ( std::string * knotName ) 02533 { 02534 // Find the knot that match with the Dowker notation 02535 int knotID = Data::DatabaseDowkerNotation::FindKnotOfDowkerNotation( 02536 m_iNumCrossingPairs, m_iaDowkerNotation, knotName ); 02537 02538 // Include the Dowker notation in the return string 02539 if ( knotName ) { 02540 if ( knotID >= 0 ) { 02541 *knotName = Data::DatabaseDowkerNotation::GetStrEntry( knotID ); 02542 } 02543 else { 02544 *knotName = "n/a"; 02545 } 02546 } 02547 02548 return knotID; // return -1 if not found, otherwise the knotID 02549 } 02550 //----------------------------------------------------------------------------- 02551 // End Check Crossings for Knot Recognition by Dowker Notation 02552 //============================================================================= 02553 #endif//TAPs_STRAND_KNOT_RECOGNITION_BY_DOWKER_NOTATION 02554 02555 //----------------------------------------------------------------------------- 02556 // Reset 02557 template <typename T> 02558 void ModelStrand<T>::Reset () 02559 { 02560 for ( int i = 0; i < m_iNoLinks; ++i ) { 02561 //--------------------------------------- 02562 m_prIsFixed[i] = false; 02563 //--------------------------------------- 02564 //m_prWasIntersect[i] = 0; 02565 //--------------------------------------- 02566 m_prVelocity[i].SetXYZ( 0, 0, 0 ); 02567 m_prForce[i].SetXYZ( 0, 0, 0 ); 02568 //--------------------------------------- 02569 #ifdef TAPs_ADVANCED_SIMULATION 02570 m_SimFlags[i].ClearAllFlags(); 02571 #endif//TAPs_ADVANCED_SIMULATION 02572 } 02573 // m_vListOfFixedPoints.clear(); // Unused (i.e. doesn't exist!) 02574 m_setOfFixedPts.clear(); 02575 02576 #ifdef TAPs_USE_EXTERNAL_ODE_SOLVER 02577 for ( unsigned int i = 0; i < x0.size(); ++i ) { 02578 x0[i] = 0; 02579 xEnd[i] = 0; 02580 } 02581 #endif//TAPs_USE_EXTERNAL_ODE_SOLVER 02582 02583 //=============================================================== 02584 #ifdef TAPs_STRAND_LOCK_SEGMENTS 02585 //--------------------------------------------------------------- 02586 ClearSegments(); 02587 //--------------------------------------------------------------- 02588 #endif//TAPs_STRAND_LOCK_SEGMENTS 02589 //=============================================================== 02590 02591 //=============================================================== 02592 #ifdef TAPs_STRAND_KNOT_CONTROL 02593 //--------------------------------------------------------------- 02594 ResetKnotControl(); 02595 //--------------------------------------------------------------- 02596 #endif//TAPs_STRAND_KNOT_CONTROL 02597 //=============================================================== 02598 02599 } // EOF: Reset () 02600 //----------------------------------------------------------------------------- 02601 // InitCurrentShape 02602 template <typename T> 02603 void ModelStrand<T>::InitCurrentShape () 02604 { 02605 static int m_iLoopSize = 16; 02606 } 02607 //----------------------------------------------------------------------------- 02608 // SetupShape Fn 02609 template <typename T> 02610 void ModelStrand<T>::SetupShape ( Vector3<T> startPosition ) 02611 { 02612 //for ( int i = 0; i <= m_iNoLinks; ++i ) { 02613 // startPosition[0] += m_tLinkLength; 02614 // m_prVertex[i] = startPosition; 02615 //} 02616 02617 /* 02618 // Case m_iNoLinks == 6 02619 m_prVertex[0] = Vector3<T>( 0,0,0 ); 02620 m_prVertex[1] = Vector3<T>( 1,0,0 ); 02621 m_prVertex[2] = Vector3<T>( 1,1,0 ); 02622 m_prVertex[3] = Vector3<T>( 1,1,1 ); 02623 m_prVertex[4] = Vector3<T>( 2,1,1 ); 02624 m_prVertex[5] = Vector3<T>( 2,0,1 ); 02625 m_prVertex[6] = Vector3<T>( 3,0,1 ); 02626 //*/ 02627 02628 //* 02629 //------------------------------------------- 02630 int i = 0; 02631 T posNev = 1; 02632 T countStep = 0.01; 02633 T count = countStep; 02634 T deg = 10; T step = -17; 02635 //T deg = 120; T step = -50; 02636 m_prVertex[i++] = startPosition; 02637 while ( i <= m_iNoLinks ) { 02638 Vector3<T> v( m_tLinkLength, 0, 0 ); 02639 T rad = deg * 3.14156 / 180.0; 02640 T c = cos(rad); 02641 T s = sin(rad); 02642 // y rotation matrix 02643 Matrix3x3<T> Ry( c, 0, -s, 02644 0, 1, 0, 02645 s, 0, c ); 02646 // x rotation matrix 02647 T cx = cos(count); 02648 T sx = sin(count); 02649 count += countStep; 02650 Matrix3x3<T> Rx( 1, 0, 0, 02651 0, cx, sx, 02652 0, -sx, cx ); 02653 v = Rx * Ry * v; 02654 m_prVertex[i] = m_prVertex[i-1] - v; 02655 ++i; 02656 deg += step; 02657 if ( deg <= -90 || 90 <= deg ) { 02658 step *= -1; 02659 } 02660 } 02661 //------------------------------------------- 02662 //*/ 02663 02664 /* 02665 //------------------------------------------- 02666 // Setup strand as a straight line 02667 int i = 0; 02668 m_prVertex[i++] = startPosition; 02669 while ( i <= m_iNoLinks ) { 02670 m_prVertex[i] = m_prVertex[i-1]; 02671 m_prVertex[i][0] += m_tLinkLength; 02672 ++i; 02673 } 02674 //------------------------------------------- 02675 //*/ 02676 } 02677 //----------------------------------------------------------------------------- 02678 // SavePreviousPositions Fn 02679 template <typename T> 02680 void ModelStrand<T>::SavePreviousPositions () 02681 { 02682 std::cout << __FILE__ << ":" << __LINE__ << ": SavePreviousPositions()\n"; 02683 for ( int i = 0; i <= m_iNoLinks; ++i ) { 02684 m_prVertexPrevPos[i] = m_prVertex[i]; 02685 } 02686 } 02687 //----------------------------------------------------------------------------- 02688 // RestorePreviousPositions Fn 02689 template <typename T> 02690 void ModelStrand<T>::RestorePreviousPositions () 02691 { 02692 for ( int i = 0; i <= m_iNoLinks; ++i ) { 02693 m_prVertex[i] = m_prVertexPrevPos[i]; 02694 } 02695 UpdateBVHTree(); 02696 CheckSelfIntersections(); 02697 SetDisplayLinks(); 02698 } 02699 //----------------------------------------------------------------------------- 02700 02701 //============================================================================= 02702 // Calculate Forces 02703 /* 02704 //----------------------------------------------------------------------------- 02705 // Stretching and Compression Force 02706 template <typename T> 02707 Vector3<T> ModelStrand<T>::CalForceStretchingAndCompression ( int pos ) 02708 { 02709 CalLinkDirection(); 02710 //--------------------------------------------------------------- 02711 Vector3<T> force( 0, 0, 0 ); 02712 if ( pos <= 0 ) { 02713 } 02714 else { 02715 force -= (GetLinkCurrentLength( pos-1 ) - m_tLinkLength) * GetLinkUnitVector( pos-1 ); 02716 } 02717 if ( pos >= m_iNoLinks ) { 02718 } 02719 else { 02720 force += (GetLinkCurrentLength( pos ) - m_tLinkLength) * GetLinkUnitVector( pos ); 02721 } 02722 //--------------------------------------------------------------- 02723 return force * m_tKStretching; 02724 } 02725 //----------------------------------------------------------------------------- 02726 // Bending Force 02727 template <typename T> 02728 Vector3<T> ModelStrand<T>::CalForceBending ( int pos ) 02729 { 02730 Vector<T> u_p1 = GetLinkCurrentLength( pos+1 ); 02731 Vector<T> u = GetLinkCurrentLength( pos ); 02732 Vector<T> u_n1 = GetLinkCurrentLength( pos-1 ); 02733 Vector<T> u_n2 = GetLinkCurrentLength( pos-2 ); 02734 //--------------------------------------------------------------- 02735 Vector3<T> force( 0, 0, 0 ); 02736 //--------------------------------------------------------------- 02737 return force; 02738 } 02739 //----------------------------------------------------------------------------- 02740 // Twisting Force 02741 template <typename T> 02742 Vector3<T> ModelStrand<T>::CalForceTwisting ( int pos ) 02743 { 02744 //--------------------------------------------------------------- 02745 Vector3<T> force( 0, 0, 0 ); 02746 //--------------------------------------------------------------- 02747 return force; 02748 } 02749 //----------------------------------------------------------------------------- 02750 // Friction Force 02751 template <typename T> 02752 Vector3<T> ModelStrand<T>::CalForceFriction ( int pos ) 02753 { 02754 //--------------------------------------------------------------- 02755 Vector3<T> force( 0, 0, 0 ); 02756 if ( pos <= 0 ) { 02757 } 02758 else { 02759 force += m_prVelocity[pos-1]; 02760 } 02761 if ( pos >= m_iNoLinks ) { 02762 } 02763 else { 02764 force -= m_prVelocity[pos]; 02765 } 02766 //--------------------------------------------------------------- 02767 return force * m_tKFriction; 02768 } 02769 //----------------------------------------------------------------------------- 02770 // Contact Force 02771 template <typename T> 02772 Vector3<T> ModelStrand<T>::CalForceContact ( int pos ) 02773 { 02774 //--------------------------------------------------------------- 02775 Vector3<T> force( 0, 0, 0 ); 02776 //--------------------------------------------------------------- 02777 return force; 02778 } 02779 //----------------------------------------------------------------------------- 02780 // Gravity Force 02781 template <typename T> 02782 Vector3<T> ModelStrand<T>::CalForceGravity ( int pos ) 02783 { 02784 //--------------------------------------------------------------- 02785 Vector3<T> force = - ( m_tGravity * CGMath<T>::VectorY ) * m_tPointWeight; 02786 //--------------------------------------------------------------- 02787 return force; 02788 } 02789 //----------------------------------------------------------------------------- 02790 // Get Link Vector 02791 template <typename T> 02792 Vector3<T> ModelStrand<T>::GetLinkUnitVector ( int linkNo ) 02793 { 02794 return (m_prVertex[linkNo+1] - m_prVertex[linkNo]).Normalized(); 02795 } 02796 //----------------------------------------------------------------------------- 02797 // Get Link Current Length 02798 template <typename T> 02799 T ModelStrand<T>::GetLinkCurrentLength ( int linkNo ) 02800 { 02801 return (m_prVertex[linkNo+1] - m_prVertex[linkNo]).Length(); 02802 } 02803 //*/ 02804 02805 //----------------------------------------------------------------------------- 02806 // SimByForce -- Calculate the new total internal force of each link 02807 template <typename T> 02808 void ModelStrand<T>::SimByForce ( T tCurrent, T tNext ) 02809 { 02810 T dt = tNext - tCurrent; // in milli seconds 02811 //------------------------------------------------------------------ 02812 // FOR TESTING/DEBUGGING 02813 //m_prIsFixed[0] = true; 02814 //m_prIsFixed[m_iNoLinks/2] = true; 02815 //m_prIsFixed[m_iNoLinks] = true; 02816 //------------------------------------------------------------------ 02817 T length; 02818 Vector3<T> force; 02819 bool useLinearSpring = false; 02820 02821 //* 02822 //---------------------------------------------------------------- 02823 // Add Stretching and Compression Force 02824 #ifdef TAPs_STRAND_LOCK_SEGMENTS 02825 // For segment# 0 02826 { 02827 unsigned int s = 0; 02828 if ( !m_Segments[s].isLocked ) { 02829 for ( unsigned int i = m_Segments[s].start; i < m_Segments[s].end; ++i ) 02830 { 02831 m_prLinkDirection[i] = m_prVertex[i+1] - m_prVertex[i]; 02832 length = m_prLinkDirection[i].Length() - m_tLinkLength; 02833 02834 //------------------------------- 02835 // Calculate force 02836 if ( useLinearSpring ) { // Linear spring 02837 force = m_tKStretching * (length * m_prLinkDirection[i].Normalized()); 02838 } 02839 else { // Nonlinear spring 02840 T tKStretching = m_tKStretching; 02841 T absLength = fabs( length ); 02842 if ( absLength <= 0.50 ) { 02843 } 02844 else if ( absLength <= 0.75 ) { 02845 tKStretching *= 1.25; 02846 } 02847 else if ( absLength <= 0.90 ) { 02848 tKStretching *= 2.0; 02849 } 02850 else if ( absLength <= 1.50 ) { 02851 tKStretching *= 4.0; 02852 } 02853 else { 02854 tKStretching *= 8.0; 02855 } 02856 force = tKStretching * (length * m_prLinkDirection[i].Normalized()); 02857 } 02858 02859 //------------------------------- 02860 // Accumulate force 02861 if ( !m_prIsFixed[i] && !m_prIsFixed[i+1] ) { 02862 m_prForce[i] += force; 02863 m_prForce[i+1] -= force; 02864 } 02865 else if ( m_prIsFixed[i] && !m_prIsFixed[i+1] ) { 02866 m_prForce[i+1] -= force * 2; 02867 } 02868 else if ( !m_prIsFixed[i] && m_prIsFixed[i+1] ) { 02869 m_prForce[i] += force * 2; 02870 } 02871 } 02872 } 02873 } 02874 // For segment# > 0 02875 for ( unsigned int s = 1; s < m_Segments.size(); ++s ) { 02876 if ( !m_Segments[s].isLocked ) { 02877 for ( unsigned int i = m_Segments[s].start; i < m_Segments[s].end; ++i ) 02878 02879 #else //TAPs_STRAND_LOCK_SEGMENTS 02880 { 02881 { 02882 for ( int i = 0; i < m_iNoLinks; ++i ) 02883 #endif//TAPs_STRAND_LOCK_SEGMENTS 02884 { 02885 m_prLinkDirection[i] = m_prVertex[i+1] - m_prVertex[i]; 02886 length = m_prLinkDirection[i].Length() - m_tLinkLength; 02887 02888 //------------------------------- 02889 // Calculate force 02890 if ( useLinearSpring ) { // Linear spring 02891 force = m_tKStretching * (length * m_prLinkDirection[i].Normalized()); 02892 } 02893 else { // Nonlinear spring 02894 T tKStretching = m_tKStretching; 02895 T absLength = fabs( length ); 02896 if ( absLength <= 0.50 ) { 02897 } 02898 else if ( absLength <= 0.75 ) { 02899 tKStretching *= 1.25; 02900 } 02901 else if ( absLength <= 0.90 ) { 02902 tKStretching *= 2.0; 02903 } 02904 else if ( absLength <= 1.50 ) { 02905 tKStretching *= 4.0; 02906 } 02907 else { 02908 tKStretching *= 8.0; 02909 } 02910 force = tKStretching * (length * m_prLinkDirection[i].Normalized()); 02911 } 02912 02913 //------------------------------- 02914 // Accumulate force 02915 if ( !m_prIsFixed[i] && !m_prIsFixed[i+1] ) { 02916 m_prForce[i] += force; 02917 m_prForce[i+1] -= force; 02918 } 02919 else if ( m_prIsFixed[i] && !m_prIsFixed[i+1] ) { 02920 m_prForce[i+1] -= force * 2; 02921 } 02922 else if ( !m_prIsFixed[i] && m_prIsFixed[i+1] ) { 02923 m_prForce[i] += force * 2; 02924 } 02925 } 02926 } 02927 } 02928 //*/ 02929 02930 //* 02931 //---------------------------------------------------------------- 02932 // Add Bending Force 02933 Vector3<T> bendingForceA, bendingForceB; 02934 T bendingAngleA, bendingAngleB; 02935 #ifdef TAPs_STRAND_LOCK_SEGMENTS 02936 // For segment# 0 02937 { 02938 unsigned int s = 0; 02939 if ( !m_Segments[s].isLocked ) { 02940 for ( unsigned int i = m_Segments[s].start+2; i <= m_Segments[s].end-2; ++i ) 02941 { 02942 if ( !m_prIsFixed[i] ) { 02943 bendingAngleA = Math<T>::PI - 02944 Math<T>::ACos( m_prLinkDirection[i-1] * (-m_prLinkDirection[i-2]) ); 02945 bendingAngleB = Math<T>::PI - 02946 Math<T>::ACos( m_prLinkDirection[i+1] * (-m_prLinkDirection[ i ]) ); 02947 bendingForceA = bendingAngleA * m_prLinkDirection[i-1] ^ (m_prLinkDirection[i-2]^m_prLinkDirection[i-1]); 02948 bendingForceB = bendingAngleB * m_prLinkDirection[ i ] ^ (m_prLinkDirection[ i ]^m_prLinkDirection[i+1]); 02949 force = m_tKBending * ( bendingForceA + bendingForceB ); 02950 02951 m_prForce[i] += force; 02952 } 02953 } 02954 } 02955 } 02956 // For segment# > 0 02957 for ( unsigned int s = 1; s < m_Segments.size(); ++s ) { 02958 if ( !m_Segments[s].isLocked ) { 02959 for ( unsigned int i = m_Segments[s].start+2; i <= m_Segments[s].end-2; ++i ) 02960 02961 #else //TAPs_STRAND_LOCK_SEGMENTS 02962 { 02963 { 02964 for ( int i = 2; i <= m_iNoLinks-2; ++i ) 02965 #endif//TAPs_STRAND_LOCK_SEGMENTS 02966 { 02967 if ( !m_prIsFixed[i] ) { 02968 bendingAngleA = Math<T>::PI - 02969 Math<T>::ACos( m_prLinkDirection[i-1] * (-m_prLinkDirection[i-2]) ); 02970 bendingAngleB = Math<T>::PI - 02971 Math<T>::ACos( m_prLinkDirection[i+1] * (-m_prLinkDirection[ i ]) ); 02972 bendingForceA = bendingAngleA * m_prLinkDirection[i-1] ^ (m_prLinkDirection[i-2]^m_prLinkDirection[i-1]); 02973 bendingForceB = bendingAngleB * m_prLinkDirection[ i ] ^ (m_prLinkDirection[ i ]^m_prLinkDirection[i+1]); 02974 force = m_tKBending * ( bendingForceA + bendingForceB ); 02975 02976 m_prForce[i] += force; 02977 } 02978 } 02979 } 02980 } 02981 //*/ 02982 02983 //* 02984 //---------------------------------------------------------------- 02985 // Add Friction Force and Gravity Force 02986 m_tGravity = m_tKGravity * dt; 02987 #ifdef TAPs_STRAND_LOCK_SEGMENTS 02988 // For segment# 0 02989 { 02990 unsigned int s = 0; 02991 if ( !m_Segments[s].isLocked ) { 02992 for ( unsigned int i = m_Segments[s].start; i <= m_Segments[s].end; ++i ) 02993 { 02994 if ( !m_prIsFixed[i] ) { 02995 //------------------------------------------------- 02996 // Gravity 02997 //if ( m_prVertex[i][1] > 2 * m_tRadius ) { 02998 // m_prForce[i] -= ( m_tGravity * CGMath<T>::VectorY ) * m_tPointWeight; 02999 //} 03000 //else { 03001 // m_prForce[i][1] = 0; 03002 // m_prVelocity[i][1] = 0; 03003 // m_prVertex[i][1] = 0; 03004 //} 03005 //------------------------------------------------- 03006 // Friction 03007 //Vector3<T> velocity = m_prForce[i] * dt / m_tPointWeight; 03008 //Vector3<T> velocity = m_prVertex[i] - m_prVertexPrevPos[i]; 03009 if ( i == 0 || i == m_iNoLinks ) { 03010 m_prForce[i] -= m_tKFriction * m_prVelocity[i] * 2.0; 03011 //m_prForce[i] -= m_tKFriction * m_prVelocity[i]; 03012 03013 //m_prForce[i] -= m_tKFriction * velocity * 0.5; 03014 } 03015 else { 03016 m_prForce[i] -= m_tKFriction * m_prVelocity[i]; 03017 //m_prForce[i] -= m_tKFriction * velocity; 03018 03019 //m_prForce[i] -= m_tKFriction * velocity; 03020 } 03021 } 03022 } 03023 } 03024 } 03025 // For segment# > 0 03026 for ( unsigned int s = 1; s < m_Segments.size(); ++s ) { 03027 if ( !m_Segments[s].isLocked ) { 03028 for ( unsigned int i = m_Segments[s].start; i <= m_Segments[s].end; ++i ) 03029 #else //TAPs_STRAND_LOCK_SEGMENTS 03030 { 03031 { 03032 for ( int i = 0; i <= m_iNoLinks; ++i ) 03033 #endif//TAPs_STRAND_LOCK_SEGMENTS 03034 { 03035 if ( !m_prIsFixed[i] ) { 03036 //------------------------------------------------- 03037 // Gravity 03038 //if ( m_prVertex[i][1] > 2 * m_tRadius ) { 03039 // m_prForce[i] -= ( m_tGravity * CGMath<T>::VectorY ) * m_tPointWeight; 03040 //} 03041 //else { 03042 // m_prForce[i][1] = 0; 03043 // m_prVelocity[i][1] = 0; 03044 // m_prVertex[i][1] = 0; 03045 //} 03046 //------------------------------------------------- 03047 // Friction 03048 //Vector3<T> velocity = m_prForce[i] * dt / m_tPointWeight; 03049 //Vector3<T> velocity = m_prVertex[i] - m_prVertexPrevPos[i]; 03050 if ( i == 0 || i == m_iNoLinks ) { 03051 m_prForce[i] -= m_tKFriction * m_prVelocity[i] * 2.0; 03052 //m_prForce[i] -= m_tKFriction * m_prVelocity[i]; 03053 03054 //m_prForce[i] -= m_tKFriction * velocity * 0.5; 03055 } 03056 else { 03057 m_prForce[i] -= m_tKFriction * m_prVelocity[i]; 03058 //m_prForce[i] -= m_tKFriction * velocity; 03059 03060 //m_prForce[i] -= m_tKFriction * velocity; 03061 } 03062 } 03063 } 03064 } 03065 } 03066 //*/ 03067 } 03068 //----------------------------------------------------------------------------- 03069 //============================================================================= 03070 03071 //----------------------------------------------------------------------------- 03072 // Collision Detection with a multi bounding object 03073 template <typename T> 03074 void ModelStrand<T>::CDAndRForStrandWithAnMBVObj ( 03075 int iLeader, int iFollower, 03076 MultiBoundingVolume<T> const * const pMBV, 03077 TransformationSupport<T> const * const pTransform = NULL 03078 ) 03079 { 03080 //--------------------------------------------------------------- 03081 //bool isThePointInsideTheBV; // the pt is inside or outside the bv 03082 Vector3<T> vTotalDistance; // total displacement vector 03083 Vector3<T> vDistance; // displacement vector 03084 TransformationSupport<T> transform; 03085 //--------------------------------------------------------------- 03086 std::vector< BoundingVolume<T> * >::const_iterator pos = 03087 pMBV->GetBoundingVolumeList().begin(); 03088 //--------------------------------------------------------------- 03089 while ( pos != pMBV->GetBoundingVolumeList().end() ) { 03090 assert( *pos != NULL ); 03091 //isThePointInsideTheBV = false; 03092 transform.MakeIdentity(); 03093 //------------------------------------------------------ 03094 if ( pTransform ) { 03095 transform.ReturnMatrixTransform() *= pTransform->GetMatrixTransform(); 03096 } 03097 transform.ReturnMatrixTransform() *= pMBV->GetTransform().GetMatrixTransform(); 03098 transform.ReturnMatrixTransform() *= (*pos)->GetTransform().GetMatrixTransform(); 03099 //------------------------------------------------------ 03100 // Transform each vertex of the strand to the bounding volume coordinate 03101 //for ( int i = 0; i <= gModelManager->strandObj->GetNumberOfStrandLinksWithoutNeedle(); ++i ) { 03102 if ( m_iLinkKnotGrp[i] < 0 ) // if this link doesn't belong to a knot group 03103 for ( int i = iFollower; i <= iFollower; ++i ) { 03104 vDistance.SetXYZ( 0, 0, 0 ); 03105 //------------------------------------------------------ 03106 // In the local coordinate of the bounding cylinder, 03107 // the cylinder axis is parallel to z-axis 03108 // where it is shifted by the cylinder center. 03109 // The cylinder has radius, height and center. 03110 // Its height is measured from -z and +z axis 03111 // where its center is situated between height/2 in -z and +z axis. 03112 Vector3<T> location = m_prVertex[i]; 03113 location -= transform.GetTranslation(); 03114 location = transform.GetMatrixRotation().GetInverse() * location; 03115 // Shift the location of point by the cylinder center 03116 // i.e. shift the cylinder to the origin (0,0,0) 03117 location -= (*pos)->GetCenter(); 03118 //------------------------------------------------------ 03119 // Now the cylinder is centered at the origin with its axis on the z-axis 03120 // where its height is from -height/2 to +height/2. 03121 // And the input point has been transformed into the cylinder coordinate. 03122 // The test can be performed below 03123 T halfHeight = (*pos)->GetHeight()/2.0; 03124 T ptRadius = sqrt( location[0]*location[0] + location[1]*location[1] ); 03125 //====================================================== 03126 // If the point is INSIDE the cylinder 03127 //------------------------------------------------------ 03128 // If the point is within the cylinder radius 03129 if ( ptRadius <= (*pos)->GetRadius() ) { 03130 // If the point is within the cylinder height 03131 if ( -halfHeight <= location[2] && location[2] <= halfHeight ) { 03132 // Find the shortest distance vector from the point to the surface 03133 // of the cylinder 03134 T difRadius = (*pos)->GetRadius() - ptRadius; 03135 T difHeight = halfHeight - fabs( location[2] ); 03136 if ( difRadius <= difHeight ) { 03137 // If the point is on the z-axis (degenerate case) 03138 if ( difRadius >= (*pos)->GetRadius() ) { 03139 vDistance.SetXYZ( 0, (*pos)->GetRadius(), 0 ); 03140 } 03141 // If the point is NOT on the z-axis 03142 else { 03143 Vector2<T> difDirection = Vector2<T>( location[0], location[1] ); 03144 difDirection.Normalized(); 03145 difDirection *= difRadius; 03146 vDistance.SetXYZ( difDirection[0], difDirection[1], 0 ); 03147 } 03148 } 03149 else { 03150 vDistance.SetXYZ( 0, 0, location[2] >= 0 ? difHeight : -difHeight ); 03151 } 03152 //------------------------- 03153 // Now rotate it back by the rotation matrix (from the transform matrix). 03154 // REMARK: Translation (from the transform matrix) is NOT applied back, 03155 // because vDistance represents a displacement vector from 03156 // the input point to the cylinder surface. 03157 vDistance = transform.GetMatrixRotation() * vDistance; 03158 //------------------------- 03159 //isThePointInsideTheBV = true; 03160 //------------------------- 03161 Vector3<T> vOffset = vDistance.GetUnit() * m_tRadius; 03162 vTotalDistance += vDistance + vOffset; 03163 //------------------------- 03164 } 03165 vTotalDistance = vTotalDistance + m_prVertex[i] - m_prVertex[iLeader]; 03166 m_prVertex[i] = m_prVertex[iLeader] + vTotalDistance.GetUnit() * m_tLinkLength; 03167 } 03168 //--------------------------------------------- 03169 } // Next Strand Point 03170 //------------------------------------------------------ 03171 ++pos; 03172 } 03173 } 03174 //----------------------------------------------------------------------------- 03175 03176 //============================================================================= 03177 #ifdef TAPs_STRAND_LOCK_SEGMENTS 03178 //----------------------------------------------------------------------------- 03179 template <typename T> 03180 int ModelStrand<T>::DivideAtPt ( unsigned int pt ) 03181 { 03182 /* 03183 // WORK IN VC++ 2003 (I.E., VC++ .NET) 03184 // Find the segment containing the point 03185 for ( unsigned int i = 0; i < static_cast<unsigned int>( m_Segments.size() ); ++i ) { 03186 // Found the segment containin the point 03187 if ( m_Segments[i].start < pt && pt < m_Segments[i].end ) { 03188 // Devide the old segment into two segments 03189 // The old one becomes the right segment and its ID is shifted by +1 03190 unsigned int newStart = m_Segments[i].start; 03191 // 03192 // &m_Segments[i] will not be converted into iterator in VC++ later version than 2003 03193 m_Segments.insert( &m_Segments[i], IC_Segment( newStart, pt, false, true ) ); 03194 03195 m_Segments[i+1].start = pt; 03196 03197 // Fix the divided point 03198 SetFixStatusOfPtNo( pt, true ); 03199 03200 return i; 03201 } 03202 } 03203 //*/ 03204 03205 // Find the segment containing the point 03206 std::vector< IC_Segment >::iterator pos = m_Segments.begin(); 03207 int i = 0; 03208 while ( pos != m_Segments.end() ) { 03209 // Found the segment containin the point 03210 if ( pos->start < pt && pt < pos->end ) { 03211 // Devide the old segment into two segments 03212 // The old one becomes the right segment and its ID is shifted by +1 03213 unsigned int newStart = pos->start; 03214 // 03215 m_Segments.insert( pos, IC_Segment( newStart, pt, false, true ) ); 03216 03217 // DOESN'T WORK!!! WHY??? 03218 //++pos; 03219 //pos->start = pt; 03220 03221 // USE THIS INSTEAD 03222 m_Segments[i+1].start = pt; 03223 03224 // Fix the divided point 03225 SetFixStatusOfPtNo( pt, true ); 03226 03227 return i; 03228 } 03229 ++i; 03230 ++pos; 03231 } 03232 03233 return -1; // cannot divide the strand at the pt 03234 } 03235 //----------------------------------------------------------------------------- 03236 template <typename T> 03237 int ModelStrand<T>::GetStartPtOfSegment ( unsigned int segment ) 03238 { 03239 if ( !ValidateSegment( segment ) ) return -1; 03240 return m_Segments[segment].start; 03241 } 03242 //----------------------------------------------------------------------------- 03243 template <typename T> 03244 int ModelStrand<T>::GetEndPtOfSegment ( unsigned int segment ) 03245 { 03246 if ( !ValidateSegment( segment ) ) return -1; 03247 return m_Segments[segment].end; 03248 } 03249 //----------------------------------------------------------------------------- 03250 template <typename T> 03251 bool ModelStrand<T>::GetSegmentLockStatus ( unsigned int segment ) 03252 { 03253 if ( !ValidateSegment( segment ) ) return false; 03254 return m_Segments[segment].isLocked; 03255 } 03256 //----------------------------------------------------------------------------- 03257 template <typename T> 03258 bool ModelStrand<T>::GetSegmentVisibleStatus ( unsigned int segment ) 03259 { 03260 if ( !ValidateSegment( segment ) ) return false; 03261 return m_Segments[segment].isVisible; 03262 } 03263 //----------------------------------------------------------------------------- 03264 template <typename T> 03265 void ModelStrand<T>::SetSegmentLockStatus ( unsigned int segment, bool status ) 03266 { 03267 if ( !ValidateSegment( segment ) ) return; 03268 m_Segments[segment].isLocked = status; 03269 03270 #ifdef TAPs_ADVANCED_SIMULATION 03271 if ( status ) { 03272 for ( unsigned int i = m_Segments[segment].start; i < m_Segments[segment].end; ++i ) { 03273 m_prIsLocked[i] = status; 03274 SetFixStatusOfPtNo( i, status ); 03275 m_SimFlags[i].SetSimulationConstraints( TAPs::Enum::AddOn::FIXED ); 03276 } 03277 } 03278 else { 03279 for ( unsigned int i = m_Segments[segment].start; i < m_Segments[segment].end; ++i ) { 03280 m_prIsLocked[i] = status; 03281 SetFixStatusOfPtNo( i, status ); 03282 m_SimFlags[i].ClearSimulationConstraints( TAPs::Enum::AddOn::FIXED ); 03283 } 03284 } 03285 #else //TAPs_ADVANCED_SIMULATION 03286 for ( unsigned int i = m_Segments[segment].start; i < m_Segments[segment].end; ++i ) { 03287 m_prIsLocked[i] = status; 03288 SetFixStatusOfPtNo( i, status ); 03289 } 03290 #endif//TAPs_ADVANCED_SIMULATION 03291 03292 /* 03293 if ( status == true ) { 03294 03295 // Tighten the first and the last link of the lock segment 03296 // I.e. make each one's length the rest length if its length is greater than the rest length 03297 03298 // The start of the segment 03299 T length = m_prVertex[m_Segments[segment].start].Length(); 03300 if ( length > m_tLinkLength ) { 03301 m_prVertex[m_Segments[segment].start] = 03302 (m_prVertex[m_Segments[segment].start] - m_prVertex[m_Segments[segment].start + 1]) * length * 2//m_tLinkLength/length 03303 + m_prVertex[m_Segments[segment].start + 1]; 03304 } 03305 03306 // The end of the segment 03307 length = m_prVertex[m_Segments[segment].end-1].Length(); 03308 if ( length > m_tLinkLength ) { 03309 m_prVertex[m_Segments[segment].end] = 03310 (m_prVertex[m_Segments[segment].end] - m_prVertex[m_Segments[segment].end - 1]) * m_tLinkLength/length 03311 + m_prVertex[m_Segments[segment].end - 1]; 03312 } 03313 03314 // DEBUG 03315 std::cout << "LOCK segment#" << segment << " [start,end]: [" << m_Segments[segment].start << "," << m_Segments[segment].end << "]\n"; 03316 } 03317 //*/ 03318 } 03319 //----------------------------------------------------------------------------- 03320 template <typename T> 03321 void ModelStrand<T>::SetSegmentVisibleStatus ( unsigned int segment, bool status ) 03322 { 03323 if ( !ValidateSegment( segment ) ) return; 03324 m_Segments[segment].isVisible = status; 03325 } 03326 //----------------------------------------------------------------------------- 03327 #endif//TAPs_STRAND_LOCK_SEGMENTS 03328 //============================================================================= 03329 03330 //============================================================================= 03331 #ifdef TAPs_STRAND_KNOT_CONTROL 03332 //----------------------------------------------------------------------------- 03333 template <typename T> 03334 void ModelStrand<T>::CreateKnotControl ( unsigned char numKnotAllowed ) 03335 { 03336 m_ucMaxNumKnotsAllowed = numKnotAllowed; 03337 m_piKnotID = new int[ m_ucMaxNumKnotsAllowed ]; 03338 ResetKnotControl(); 03339 //=============================================================== 03340 #ifdef TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 03341 //--------------------------------------------------------------- 03342 m_WaitingTime = 5.0; // set waiting time 03343 03344 m_uiCounterThreshold = 20; // act as a timer for fixing the current knot 03345 03346 m_uiMinLengthThreshold = 0; // start at zero 03347 03348 m_uiLengthThreshold[0] = 12; // length threshold for half knot -- basic knot 03349 // extra length threshold for double knot will be added by m_uiLengthThreshold[0]/2 03350 m_uiLengthThreshold[1] = 7; // extra length threshold for double knot 03351 // i.e. for double knot the length threshold is 18 (of half knot) + 8 03352 03353 // Unused for now 03354 m_uiLengthThreshold[2] = 8; // length threshold for ... 03355 m_uiLengthThreshold[3] = 8; // length threshold for ... 03356 m_uiLengthThreshold[4] = 8; // length threshold for ... 03357 m_uiLengthThreshold[5] = 8; // length threshold for ... 03358 m_uiLengthThreshold[6] = 8; // length threshold for ... 03359 m_uiLengthThreshold[7] = 8; // length threshold for ... 03360 //--------------------------------------------------------------- 03361 #endif//TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 03362 //=============================================================== 03363 } 03364 //----------------------------------------------------------------------------- 03365 template <typename T> 03366 void ModelStrand<T>::DeleteKnotControl () 03367 { 03368 if ( m_piKnotID ) { 03369 delete [] m_piKnotID; 03370 m_piKnotID = NULL; 03371 } 03372 } 03373 //----------------------------------------------------------------------------- 03374 template <typename T> 03375 void ModelStrand<T>::InitKnotControl ( unsigned char numKnotAllowed ) 03376 { 03377 DeleteKnotControl(); 03378 CreateKnotControl( numKnotAllowed ); 03379 } 03380 //----------------------------------------------------------------------------- 03381 template <typename T> 03382 void ModelStrand<T>::ResetKnotControl () 03383 { 03384 m_ucKnotCount = 0; 03385 for ( int i = 0; i < m_ucMaxNumKnotsAllowed; ++i ) { 03386 m_piKnotID[i] = -1; 03387 } 03388 //=============================================================== 03389 #ifdef TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 03390 //--------------------------------------------------------------- 03391 m_uiCounterForFixingKnot = 0; // reset counter 03392 m_uiMinLengthThreshold = 0; 03393 ResetElapsedTime(); 03394 m_uiLengthAccumulateTarget = m_uiLengthThreshold[0]; // reset accumulated target length 03395 m_ucTrackingKnot = Data::DatabaseDowkerNotation::UNDEFINED; // reset tracker 03396 //--------------------------------------------------------------- 03397 #endif//TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 03398 //=============================================================== 03399 } 03400 //----------------------------------------------------------------------------- 03401 template <typename T> 03402 std::string ModelStrand<T>::CheckSurgeonsKnot () 03403 { 03404 //=============================================================== 03405 #ifdef TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 03406 //--------------------------------------------------------------- 03407 std::string str; 03408 static std::string name; 03409 03410 // Recognize the knot 03411 //* 03412 if ( m_ucTrackingKnot == Data::DatabaseDowkerNotation::UNDEFINED ) { 03413 03414 // Check if a new knot is being formed 03415 m_ucTrackingKnot = DowkerNotationToKnotName( &name ); 03416 03417 // For current update, CheckSelfCrossingForKnotRecognition fn should be before DowkerNotationToKnotName fn 03418 #ifdef TAPs_STRAND_DEBUG 03419 special_debug_knotID = 03420 #endif//TAPs_STRAND_DEBUG 03421 CheckSelfCrossingForKnotRecognition( GetProjectionDirection( m_prVertex[0], m_prVertex[m_iNoLinks/2], m_prVertex[m_iNoLinks] ) ); 03422 int start = GetKnotStartPt(); 03423 int end = GetKnotEndPt(); 03424 03425 // Recognize the knot -- Total Knots is One 03426 if ( m_ucKnotCount == 1 ) { 03427 str = GetNameOfKnot( 0, false ); // 2nd parameter: true with (-)/(+) for direction 03428 str += " Knot"; 03429 //str = "One Knot"; 03430 } 03431 03432 // Recognize the knot -- Total Knots is Two 03433 else if ( m_ucKnotCount == 2 ) { 03434 //----------------------------------- 03435 // Check Surgeon's Knot (NEG-then-POS or POS-then-NEG) 03436 if ( 03437 // neg double then pos half equals surgeon's knot 03438 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::DOUBLE_NEG 03439 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS ) 03440 || 03441 // pos double then neg half equals surgeon's knot 03442 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::DOUBLE_POS 03443 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG ) 03444 ) { 03445 str = "Surgeon's Knot"; 03446 } 03447 //----------------------------------- 03448 // Check Surgeon's Knot (NEG-then-NEG or POS-then-POS) 03449 else if ( 03450 // neg double then pos half equals surgeon's knot 03451 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::DOUBLE_NEG 03452 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG ) 03453 || 03454 // pos double then neg half equals surgeon's knot 03455 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::DOUBLE_POS 03456 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS ) 03457 ) { 03458 str = "Granny Double Knot"; 03459 } 03460 //----------------------------------- 03461 // Check Square Knot (NEG-then-POS or POS-then-NEG) 03462 else if ( 03463 // neg half then pos half equals square knot 03464 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::HALF_NEG 03465 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS ) 03466 || 03467 // pos half then neg half equals square knot 03468 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::HALF_POS 03469 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG ) 03470 ) { 03471 str = "Square Knot"; 03472 } 03473 //----------------------------------- 03474 // Check Square Knot (NEG-then-NEG or POS-then-POS) 03475 else if ( 03476 // neg half then pos half equals square knot 03477 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::HALF_NEG 03478 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG ) 03479 || 03480 // pos half then neg half equals square knot 03481 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::HALF_POS 03482 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS ) 03483 ) { 03484 str = "Granny Knot"; 03485 } 03486 //----------------------------------- 03487 // Unrecognized Knot Combination 03488 else { 03489 char s[16]; 03490 str = _itoa( m_ucKnotCount, s, 10 ); 03491 str += " knot combination: "; 03492 03493 //* 03494 #ifdef TAPs_STRAND_DEBUG 03495 for ( int i = 0; i < m_ucKnotCount; ++i ) { 03496 //str += itoa( m_piKnotID[i], s, 10 ); 03497 str += GetNameOfKnot( i, true ); // 2nd parameter: true with (-)/(+) for direction 03498 if ( i < m_ucKnotCount-1 ) str += ", "; 03499 } 03500 #endif//TAPs_STRAND_DEBUG 03501 //*/ 03502 str += GetStrNameForKnotCombination(); 03503 } 03504 } 03505 03506 // Recognize the knot -- Total Knots is Three 03507 else if ( m_ucKnotCount == 3 ) { 03508 //----------------------------------- 03509 // Check Surgeon's Knot (NEG-then-POS-then-NEG or POS-then-NEG-then-POS) 03510 if ( 03511 // neg double then pos half equals surgeon's knot 03512 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::DOUBLE_NEG 03513 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS 03514 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG ) 03515 || 03516 // pos double then neg half equals surgeon's knot 03517 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::DOUBLE_POS 03518 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG 03519 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS ) 03520 ) { 03521 str = "Square Surgeon's Knot"; 03522 } 03523 //----------------------------------- 03524 // Check Surgeon's Knot (NEG-then-NEG-then-NEG or POS-then-POS-then-POS) 03525 else if ( 03526 // neg double then pos half equals surgeon's knot 03527 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::DOUBLE_NEG 03528 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG 03529 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG ) 03530 || 03531 // pos double then neg half equals surgeon's knot 03532 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::DOUBLE_POS 03533 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS 03534 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS ) 03535 ) { 03536 str = "Granny Granny Double Knot"; 03537 } 03538 //----------------------------------- 03539 // Check Square's Knot (NEG-then-POS-then-NEG or POS-then-NEG-then-POS) 03540 else if ( 03541 // neg double then pos half equals surgeon's knot 03542 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::HALF_NEG 03543 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS 03544 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG ) 03545 || 03546 // pos double then neg half equals surgeon's knot 03547 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::HALF_POS 03548 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG 03549 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS ) 03550 ) { 03551 str = "Square Square Knot"; 03552 } 03553 //----------------------------------- 03554 // Check Square's Knot (NEG-then-NEG-then-NEG or POS-then-POS-then-POS) 03555 else if ( 03556 // neg double then pos half equals surgeon's knot 03557 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::HALF_NEG 03558 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG 03559 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_NEG ) 03560 || 03561 // pos double then neg half equals surgeon's knot 03562 ( m_piKnotID[0] == Data::DatabaseDowkerNotation::HALF_POS 03563 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS 03564 && m_piKnotID[1] == Data::DatabaseDowkerNotation::HALF_POS ) 03565 ) { 03566 str = "Granny Granny Knot"; 03567 } 03568 //----------------------------------- 03569 // Unrecognized Knot Combination 03570 else { 03571 char s[16]; 03572 str = _itoa( m_ucKnotCount, s, 10 ); 03573 str += " knot combination: "; 03574 03575 //* 03576 #ifdef TAPs_STRAND_DEBUG 03577 for ( int i = 0; i < m_ucKnotCount; ++i ) { 03578 //str += itoa( m_piKnotID[i], s, 10 ); 03579 str += GetNameOfKnot( i, true ); // 2nd parameter: true with (-)/(+) for direction 03580 if ( i < m_ucKnotCount-1 ) str += ", "; 03581 } 03582 #endif//TAPs_STRAND_DEBUG 03583 //*/ 03584 str += GetStrNameForKnotCombination(); 03585 } 03586 } 03587 03588 // Recognize the knot -- Total Knots is greater than three 03589 else { 03590 char s[16]; 03591 str = _itoa( m_ucKnotCount, s, 10 ); 03592 str += " knot combination: "; 03593 03594 //* 03595 #ifdef TAPs_STRAND_DEBUG 03596 for ( int i = 0; i < m_ucKnotCount; ++i ) { 03597 //str += itoa( m_piKnotID[i], s, 10 ); 03598 str += GetNameOfKnot( i, true ); // 2nd parameter: true with (-)/(+) for direction 03599 if ( i < m_ucKnotCount-1 ) str += ", "; 03600 } 03601 #endif//TAPs_STRAND_DEBUG 03602 //*/ 03603 str += GetStrNameForKnotCombination(); 03604 } 03605 } 03606 //*/ 03607 03608 /* 03609 // DEBUG 03610 if ( m_ucTrackingKnot == Data::DatabaseDowkerNotation::UNDEFINED ) { 03611 // Check if a new knot is being formed 03612 m_ucTrackingKnot = DowkerNotationToKnotName( &name ); 03613 03614 // For current update, CheckSelfCrossingForKnotRecognition fn should be before DowkerNotationToKnotName fn 03615 #ifdef TAPs_STRAND_DEBUG 03616 special_debug_knotID = 03617 #endif//TAPs_STRAND_DEBUG 03618 Vector3<T> v; 03619 CheckSelfCrossingForKnotRecognition( GetProjectionDirection( StartPoint, MiddlePoint, EndPoint ) ); 03620 int start = GetKnotStartPt(); 03621 int end = GetKnotEndPt(); 03622 03623 char s[16]; 03624 str = itoa( m_ucKnotCount, s, 10 ); 03625 str += " knot combination: "; 03626 for ( int i = 0; i < m_ucKnotCount; ++i ) { 03627 str += itoa( m_piKnotID[i], s, 10 ); 03628 if ( i < m_ucKnotCount-1 ) str += ", "; 03629 } 03630 } 03631 //*/ 03632 03633 03634 // Track the current knot 03635 else { 03636 // For current update, CheckSelfCrossingForKnotRecognition fn should be before DowkerNotationToKnotName fn 03637 #ifdef TAPs_STRAND_DEBUG 03638 special_debug_knotID = 03639 #endif//TAPs_STRAND_DEBUG 03640 CheckSelfCrossingForKnotRecognition( GetProjectionDirection( m_prVertex[0], m_prVertex[m_iNoLinks/2], m_prVertex[m_iNoLinks] ) ); 03641 int start = GetKnotStartPt(); 03642 int end = GetKnotEndPt(); 03643 03644 //------------------------------------------------- 03645 // Change tracking knot -- for a more complex knot 03646 03647 //#ifdef TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 03648 //#else //TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 03649 // Current tracked knot is a half knot 03650 if ( m_ucTrackingKnot == Data::DatabaseDowkerNotation::HALF_NEG 03651 || m_ucTrackingKnot == Data::DatabaseDowkerNotation::HALF_POS ) 03652 { 03653 // Check the current knot 03654 std::string name2; 03655 int knot = DowkerNotationToKnotName( &name2 ); 03656 03657 // The current knot is not a half knot 03658 if ( knot != Data::DatabaseDowkerNotation::UNDEFINED ) { 03665 //if ( knot == Data::DatabaseDowkerNotation::HALF_NEG 03666 // || knot == Data::DatabaseDowkerNotation::HALF_POS ) 03667 //{ 03668 // // Change from half knot to half knot 03669 // str = name = name2; 03670 // m_ucTrackingKnot = knot; 03671 //} 03672 //else 03673 if ( knot == Data::DatabaseDowkerNotation::DOUBLE_NEG 03674 || knot == Data::DatabaseDowkerNotation::DOUBLE_POS ) 03675 { 03676 // Change from half knot to double knot 03677 str = name = name2; 03678 m_ucTrackingKnot = knot; 03679 // Add extra length threshold for the knot change 03680 m_uiLengthAccumulateTarget += m_uiLengthThreshold[0] / 2; 03681 } 03682 } 03683 } 03684 //#endif//TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 03685 03686 //------------------------------------------------- 03687 // A new knot is formed or being tracked 03688 if ( m_ucTrackingKnot != Data::DatabaseDowkerNotation::UNDEFINED ) { 03689 03690 /* 03691 #ifdef TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 03692 if ( IsClumped() ) { 03693 char val[16]; 03694 str = "Tracking Knot# "; 03695 str += itoa(m_ucKnotCount+1, val, 10); 03696 str += " (" + name + ")"; 03697 03698 str += " ID: "; 03699 str += itoa(m_ucTrackingKnot, val, 10); 03700 03701 int knotLength = end-start; 03702 03703 if ( m_ucKnotCount == 0 ) { 03704 if ( ++m_uiCounterForFixingKnot > m_uiCounterThreshold ) { 03705 // Divide strand into segments 03706 DivideAtPt( start ); 03707 int segmentID = DivideAtPt( end ); 03708 SetSegmentLockStatus( segmentID, true ); 03709 03710 // Record knot ID and increase knot count 03711 m_piKnotID[m_ucKnotCount++] = m_ucTrackingKnot; 03712 // Reset counter and set the new accumulated target length for next knot 03713 m_uiCounterForFixingKnot = 0; 03714 m_uiLengthAccumulateTarget = knotLength + m_uiLengthThreshold[0]; 03715 // Reset tracking knot 03716 m_ucTrackingKnot = Data::DatabaseDowkerNotation::UNDEFINED; 03717 str = ""; 03718 03719 // DEBUG 03720 //PrtSegments(); 03721 //std::cout << "Fix Knot#: " << m_ucKnotCount << "\n"; 03722 } 03723 } 03724 else if ( 0 < m_ucKnotCount && m_ucKnotCount < m_ucMaxNumKnotsAllowed ) { 03725 if ( ++m_uiCounterForFixingKnot > m_uiCounterThreshold ) { 03726 // Create left segment 03727 int segmentID1 = DivideAtPt( start ); 03728 SetSegmentLockStatus( segmentID1+1, true ); 03729 // Create right segment 03730 int segmentID2 = DivideAtPt( end ); 03731 SetSegmentLockStatus( segmentID2, true ); 03732 03733 // Record knot ID and increase knot count 03734 m_piKnotID[m_ucKnotCount++] = m_ucTrackingKnot; 03735 // Reset counter and set the new accumulated target length for next knot 03736 m_uiCounterForFixingKnot = 0; 03737 m_uiLengthAccumulateTarget = knotLength + m_uiLengthThreshold[m_ucKnotCount]; 03738 // Reset tracking knot 03739 m_ucTrackingKnot = Data::DatabaseDowkerNotation::UNDEFINED; 03740 str = ""; 03741 03742 // DEBUG 03743 //PrtSegments(); 03744 //std::cout << "Fix Knot#: " << m_ucKnotCount << "\n"; 03745 } 03746 } 03747 03748 return str; 03749 } 03750 #endif//TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 03751 //*/ 03752 03753 // Recovering from incorrect collision detection 03754 // Case when there was a knot then there is no crossing pairs 03755 if ( m_iNumCrossingPairs == 0 ) { 03756 m_ucTrackingKnot = Data::DatabaseDowkerNotation::UNDEFINED; 03757 str = "Recovering from an error!"; 03758 03759 m_uiCounterForFixingKnot = 0; 03760 ResetElapsedTime(); 03761 03762 // DEBUG 03763 //std::cout << "m_iNumCrossingPairs was ZERO!\n" << std::endl; 03764 } 03765 03766 char val[16]; 03767 str = "Tracking Knot# "; 03768 str += _itoa(m_ucKnotCount+1, val, 10); 03769 str += " (" + name + ")"; 03770 03771 str += " ID: "; 03772 str += _itoa(m_ucTrackingKnot, val, 10); 03773 03774 // DEBUG 03775 //std::cout << "end-start: " << end-start << " = " << end << " - " << start << "\n"; 03776 //std::cout << "TargetLength: " << m_uiLengthAccumulateTarget << "\n"; 03777 //std::cout << "CounterForFixingKnot: " << m_uiCounterForFixingKnot << "\n"; 03778 03779 //----------------------------------- 03780 // Skip invalid length 03781 if ( end < 0 || start < 0 ) { 03782 //++m_uiCounterForFixingKnot; 03783 } 03784 //----------------------------------- 03785 // Track the first knot 03786 else if ( m_ucKnotCount == 0 ) { 03787 int knotLength = end-start; 03788 if ( knotLength >= static_cast<int>( m_uiMinLengthThreshold ) || static_cast<int>( m_uiCounterForFixingKnot ) > m_uiCounterThreshold ) { 03789 if ( knotLength < static_cast<int>( m_uiLengthAccumulateTarget ) ) { 03790 // Reset counter and set new accumulated target length 03791 m_uiCounterForFixingKnot = 0; 03792 m_uiLengthAccumulateTarget = knotLength; 03793 ResetElapsedTime(); 03794 } 03795 else if ( ( knotLength <= static_cast<int>( m_uiLengthAccumulateTarget ) + 2 ) ) { 03796 if ( ++m_uiCounterForFixingKnot >= m_uiCounterThreshold ) { 03797 // Divide strand into segments 03798 DivideAtPt( start ); 03799 int segmentID = DivideAtPt( end ); 03800 SetSegmentLockStatus( segmentID, true ); 03801 03802 // Record knot ID and increase knot count 03803 m_piKnotID[m_ucKnotCount++] = m_ucTrackingKnot; 03804 // Reset counter and set the new accumulated target length for next knot 03805 m_uiCounterForFixingKnot = 0; 03806 ResetElapsedTime(); 03807 if ( knotLength >= static_cast<int>( m_uiMinLengthThreshold ) ) { 03808 m_uiMinLengthThreshold = knotLength; // new min length 03809 } 03810 m_uiLengthAccumulateTarget = m_uiMinLengthThreshold + m_uiLengthThreshold[m_ucKnotCount]; 03811 // Reset tracking knot 03812 m_ucTrackingKnot = Data::DatabaseDowkerNotation::UNDEFINED; 03813 str = ""; 03814 03815 // DEBUG 03816 //PrtSegments(); 03817 //std::cout << "Fix Knot#: " << m_ucKnotCount << "\n"; 03818 } 03819 } 03820 else { 03821 ++m_uiCounterForFixingKnot; 03822 AddElapsedTime(); 03823 } 03824 } 03825 } 03826 //----------------------------------- 03827 // Tracking the second, third, and so on 03828 else if ( 0 < m_ucKnotCount && m_ucKnotCount < m_ucMaxNumKnotsAllowed ) { 03829 int knotLength = end-start; 03830 if ( knotLength >= static_cast<int>( m_uiMinLengthThreshold ) || static_cast<int>( m_uiCounterForFixingKnot ) > m_uiCounterThreshold ) { 03831 if ( knotLength < static_cast<int>( m_uiLengthAccumulateTarget ) ) { 03832 // Reset counter and set new accumulated target length 03833 m_uiCounterForFixingKnot = 0; 03834 m_uiLengthAccumulateTarget = knotLength; 03835 ResetElapsedTime(); 03836 } 03837 else if ( ( knotLength <= static_cast<int>( m_uiLengthAccumulateTarget ) + 2 ) || 03838 03839 ( IsTimeLimitReached() && knotLength <= static_cast<int>( m_uiLengthAccumulateTarget ) + 4 ) ) { 03840 03841 //(m_uiCounterForFixingKnot >= 125) ) { 03842 03843 #ifdef TAPs_STRAND_DEBUG 03844 if ( IsTimeLimitReached() ) { 03845 std::cout << "Elapsed Time: " << m_AccTime << "\n"; 03846 } 03847 #endif//TAPs_STRAND_DEBUG 03848 03849 if ( ++m_uiCounterForFixingKnot >= m_uiCounterThreshold ) { 03850 // Create left segment 03851 int segmentID1 = DivideAtPt( start ); 03852 SetSegmentLockStatus( segmentID1+1, true ); 03853 // Create right segment 03854 int segmentID2 = DivideAtPt( end ); 03855 SetSegmentLockStatus( segmentID2, true ); 03856 03857 // Record knot ID and increase knot count 03858 m_piKnotID[m_ucKnotCount++] = m_ucTrackingKnot; 03859 // Reset counter and set the new accumulated target length for next knot 03860 m_uiCounterForFixingKnot = 0; 03861 ResetElapsedTime(); 03862 if ( knotLength >= static_cast<int>( m_uiMinLengthThreshold ) ) { 03863 m_uiMinLengthThreshold = knotLength; // new min length 03864 } 03865 m_uiLengthAccumulateTarget = m_uiMinLengthThreshold + m_uiLengthThreshold[m_ucKnotCount]; 03866 // Reset tracking knot 03867 m_ucTrackingKnot = Data::DatabaseDowkerNotation::UNDEFINED; 03868 str = ""; 03869 03870 // DEBUG 03871 //PrtSegments(); 03872 //std::cout << "Fix Knot#: " << m_ucKnotCount << "\n"; 03873 } 03874 } 03875 else { 03876 ++m_uiCounterForFixingKnot; 03877 AddElapsedTime(); 03878 } 03879 } 03880 } 03881 } 03882 //std::cout << "Acc Time: " << m_AccTime << "\n"; 03883 } 03884 ResetStartTime(); 03885 return str; 03886 03887 #else //TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 03888 return ""; 03889 03890 //--------------------------------------------------------------- 03891 #endif//TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 03892 //=============================================================== 03893 03894 } 03895 //----------------------------------------------------------------------------- 03896 template <typename T> 03897 std::string ModelStrand<T>::GetStrNameForKnotCombination () 03898 { 03899 std::string str; 03900 for ( int i = 1; i < m_ucKnotCount; ++i ) { 03901 if ( m_piKnotID[i-1] == 0 ) { 03902 if ( m_piKnotID[i] == 0 ) { 03903 str = "Granny " + str; 03904 } 03905 else if ( m_piKnotID[i] == 1 ) { 03906 str = "Square " + str; 03907 } 03908 } 03909 else if ( m_piKnotID[i-1] == 1 ) { 03910 if ( m_piKnotID[i] == 1 ) { 03911 str = "Granny " + str; 03912 } 03913 else if ( m_piKnotID[i] == 0 ) { 03914 str = "Square " + str; 03915 } 03916 } 03917 } 03918 return str + " Knot"; 03919 } 03920 03921 #ifdef TAPs_COLLECT_DATA 03922 //----------------------------------------------------------------------------- 03923 template <typename T> 03924 std::string ModelStrand<T>::GetNameOfKnot ( unsigned int i, bool withPosOrNegPostfix ) 03925 { 03926 if ( i >= m_ucKnotCount ) return "n\a"; 03927 if ( withPosOrNegPostfix ) { 03928 if ( m_piKnotID[i] % 2 == 0 ) { 03929 return Data::DatabaseDowkerNotation::GetKnotName( m_piKnotID[i]/2 ) + "(-)"; 03930 } 03931 else { 03932 return Data::DatabaseDowkerNotation::GetKnotName( m_piKnotID[i]/2 ) + "(+)"; 03933 } 03934 } 03935 return Data::DatabaseDowkerNotation::GetKnotName( m_piKnotID[i]/2 ); 03936 } 03937 //----------------------------------------------------------------------------- 03938 template <typename T> 03939 int ModelStrand<T>::GetIDOfKnot ( unsigned int i ) 03940 { 03941 if ( i >= m_ucKnotCount ) return -1; 03942 return m_piKnotID[i]; 03943 } 03944 //----------------------------------------------------------------------------- 03945 #endif//TAPs_COLLECT_DATA 03946 03947 03948 //=================================================================== 03949 #ifdef TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 03950 //------------------------------------------------------------------- 03951 template <typename T> 03952 bool ModelStrand<T>::SetKnotControlThreshold ( Threshold th, T val ) 03953 { 03954 if ( val < 0.0 ) return false; 03955 switch ( th ) { 03956 case THRESHOLD_FOR_FIXING_KNOT: 03957 m_uiCounterThreshold = static_cast< unsigned int >( val ); 03958 return true; 03959 case THRESHOLD_WAITING_TIME: 03960 m_WaitingTime = static_cast< double >( val ); 03961 return true; 03962 case LENGTH_THRESHOLD_0: 03963 m_uiLengthThreshold[0] = static_cast< unsigned int >( val ); 03964 return true; 03965 case LENGTH_THRESHOLD_1: 03966 m_uiLengthThreshold[1] = static_cast< unsigned int >( val ); 03967 return true; 03968 case LENGTH_THRESHOLD_2: 03969 m_uiLengthThreshold[2] = static_cast< unsigned int >( val ); 03970 return true; 03971 case LENGTH_THRESHOLD_3: 03972 m_uiLengthThreshold[3] = static_cast< unsigned int >( val ); 03973 return true; 03974 case LENGTH_THRESHOLD_4: 03975 m_uiLengthThreshold[4] = static_cast< unsigned int >( val ); 03976 return true; 03977 case LENGTH_THRESHOLD_5: 03978 m_uiLengthThreshold[5] = static_cast< unsigned int >( val ); 03979 return true; 03980 case LENGTH_THRESHOLD_6: 03981 m_uiLengthThreshold[6] = static_cast< unsigned int >( val ); 03982 return true; 03983 case LENGTH_THRESHOLD_7: 03984 m_uiLengthThreshold[7] = static_cast< unsigned int >( val ); 03985 return true; 03986 } 03987 return false; 03988 } 03989 //------------------------------------------------------------------- 03990 template <typename T> 03991 T ModelStrand<T>::GetKnotControlThreshold ( Threshold th ) const 03992 { 03993 switch ( th ) { 03994 case THRESHOLD_FOR_FIXING_KNOT: 03995 return static_cast< T >( m_uiCounterThreshold ); 03996 case THRESHOLD_WAITING_TIME: 03997 return static_cast< T >( m_WaitingTime ); 03998 case LENGTH_THRESHOLD_0: 03999 return static_cast< T >( m_uiLengthThreshold[0] ); 04000 case LENGTH_THRESHOLD_1: 04001 return static_cast< T >( m_uiLengthThreshold[1] ); 04002 case LENGTH_THRESHOLD_2: 04003 return static_cast< T >( m_uiLengthThreshold[2] ); 04004 case LENGTH_THRESHOLD_3: 04005 return static_cast< T >( m_uiLengthThreshold[3] ); 04006 case LENGTH_THRESHOLD_4: 04007 return static_cast< T >( m_uiLengthThreshold[4] ); 04008 case LENGTH_THRESHOLD_5: 04009 return static_cast< T >( m_uiLengthThreshold[5] ); 04010 case LENGTH_THRESHOLD_6: 04011 return static_cast< T >( m_uiLengthThreshold[6] ); 04012 case LENGTH_THRESHOLD_7: 04013 return static_cast< T >( m_uiLengthThreshold[7] ); 04014 } 04015 return -1; 04016 } 04017 //------------------------------------------------------------------- 04018 04019 04020 //=================================================================== 04021 #ifdef TAPs_ALLOW_SETTING_PROJECTION_DIRECTION 04022 //------------------------------------------------------------------- 04023 // Find projection direction from a set of three points 04024 template <typename T> 04025 Vector3<T> ModelStrand<T>::GetProjectionDirection ( 04026 Vector3<T> const & pt1, Vector3<T> const & pt2, Vector3<T> const & pt3 ) 04027 { 04028 return TAPs::CGMath<T>::NormalOfTriangle( pt1, pt2, pt3 ); 04029 } 04030 //------------------------------------------------------------------- 04031 // Check self-crossings 04032 template <typename T> 04033 int ModelStrand<T>::CheckSelfCrossingForKnotRecognition ( 04034 Vector3<T> const & projectionDirection ) 04035 { 04036 //----------------------------------------------------- 04037 // Reset 04038 for ( int i = 0; i < m_iMaxCrossingPairs; ++i ) m_iaDowkerNotation[i] = 0; 04039 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04040 m_crossings.clear(); 04041 04042 for ( int i = 0; i < m_iNoLinks; ++i ) m_iaCrossingCounters[i] = 0; 04043 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04044 for ( int i = 0; i < m_iNoLinks; ++i ) m_iaCrossingsForDowkerNotation[i] = 0; 04045 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04046 04047 //----------------------------------------------------- 04048 // Find Crossings 04049 CheckSelfCrossingsNextLevelRecursively( m_BVHTree->Root()->Child(0), 04050 m_BVHTree->Root()->Child(1), 04051 projectionDirection ); 04052 //----------------------------------------------------- 04053 // For Recording Dowker Notation 04054 std::vector<int> crosses; 04055 std::vector<int> crossesID; 04056 04057 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04058 std::list< IC_Crossing >::const_iterator it = m_crossings.begin(); 04059 while ( it != m_crossings.end() ) { 04060 // crossesID records the node number that has another node cross over or under it. 04061 // crosses records the crossing identified by node number that crosses over the crossesID. 04062 // E.g. real cross# 1 2 3 4 5 6 04063 // crossesID: 30 31 32 74 77 79 04064 // crosses: -74 77 -79 30 -31 32 04065 // results in the Dowker notation below 04066 // Dowker#: (1,4) (3,6) (5,2) 04067 // which is a half knot 04068 crossesID.push_back( (*it).id ); 04069 crosses.push_back( (*it).number ); 04070 ++it; 04071 } 04072 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04073 for ( int i = 0; i < m_iNoLinks; ++i ) { 04074 if ( m_iaCrossingsForDowkerNotation[i] != 0 ) { 04075 // crossesID records the node number that has another node cross over or under it. 04076 // crosses records the crossing identified by node number that crosses over the crossesID. 04077 // E.g. real cross# 1 2 3 4 5 6 04078 // crossesID: 30 31 32 74 77 79 04079 // crosses: -74 77 -79 30 -31 32 04080 // results in the Dowker notation below 04081 // Dowker#: (1,4) (3,6) (5,2) 04082 // which is a half knot 04083 crossesID.push_back( i+1 ); 04084 crosses.push_back( m_iaCrossingsForDowkerNotation[i] ); 04085 } 04086 } 04087 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04088 04089 int numOfCrosses = static_cast<int>( crosses.size() ); 04090 if ( numOfCrosses == 0 ) { // Not a knot 04091 m_iKnotStartPt = m_iKnotEndPt = -1; 04092 m_iNumCrossingPairs = 0; 04093 } 04094 else if ( numOfCrosses % 2 == 0 ) { 04095 m_iNumCrossingPairs = numOfCrosses/2; 04096 assert( m_iNumCrossingPairs <= m_iMaxCrossingPairs ); 04097 int idx = 0; 04098 for ( int i = 0, odd = 1; i < numOfCrosses; i+=2, odd+=2 ) { 04099 for ( int j = 1, even = 2; j < numOfCrosses; j+=2, even+=2 ) { 04100 if ( crossesID[i] == abs( crosses[j] ) ) { 04101 //iaDowkerNotation[ idx++ ] = odd; 04102 if ( crosses[j] < 0 ) 04103 m_iaDowkerNotation[ idx++ ] = -even; 04104 else 04105 m_iaDowkerNotation[ idx++ ] = even; 04106 } 04107 } 04108 } 04109 04111 m_iKnotStartPt = crossesID[0]; 04112 m_iKnotEndPt = crossesID[numOfCrosses-1]; 04113 } 04114 else { // Not a knot 04115 m_iKnotStartPt = m_iKnotEndPt = -1; 04116 m_iNumCrossingPairs = numOfCrosses/2; 04117 } 04118 04119 #ifdef TAPs_STRAND_DEBUG 04120 debug_crosses = crosses; 04121 debug_crossesID = crossesID; 04122 std::cout << Debug_Str(); 04123 #endif//TAPs_STRAND_DEBUG 04124 04125 // Find the knot that match with the Dowker notation 04126 int knotID = DowkerNotationToKnotName(); 04127 if ( knotID >= 0 ) { 04128 //std::cout << "zDir found Knot ID# " << knotID << "\n"; 04129 return knotID; 04130 } 04131 04132 //------------------------------------------------- 04133 #ifdef TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 04134 // Check Clumped 04135 if ( m_iNumCrossingPairs > 1 ) { 04136 if ( m_ucTrackingKnot != Data::DatabaseDowkerNotation::UNDEFINED ) { 04137 T sphereRadius = m_tLinkLength * 10.0; 04138 CheckClumped( m_iKnotStartPt, m_iKnotEndPt, sphereRadius ); 04139 if ( IsClumped() ) { 04140 #ifdef TAPs_STRAND_DEBUG 04141 std::cout << "CLUMPED: true (" << m_iKnotStartPt << "," << m_iKnotEndPt << ")" << "\n"; 04142 #endif//TAPs_STRAND_DEBUG 04143 04144 m_uiCounterForFixingKnot = m_uiCounterThreshold+1; 04145 04146 #ifdef TAPs_STRAND_DEBUG 04147 std::cout << "RET: " << m_ucTrackingKnot << "\n"; 04148 #endif//TAPs_STRAND_DEBUG 04149 04150 return m_ucTrackingKnot; 04151 } 04152 } 04153 else { 04154 //std::cout << "CLUMPED: false (" << m_iKnotStartPt << "," << m_iKnotEndPt << ")" << std::endl; 04155 } 04156 } 04157 #endif//TAPs_STRAND_KNOT_RECOGNITION_ADD_ONs 04158 //------------------------------------------------- 04159 04160 // return -1 if not found, otherwise the knotID 04161 //std::cout << "Not found Knot ID# " << knotID << "\n"; 04162 return knotID; 04163 } 04164 //------------------------------------------------------------------- 04165 04166 //================================================================= 04167 // START: Fns for CheckSelfCrossingForKnotRecognition function 04168 //----------------------------------------------------------------- 04169 // CheckSelfCrossingsNextLevelRecursively 04170 // Assume no intersections between immediate adjacent links 04171 // Assume a BVH node either has both children or none, therefore 04172 // checking either it has a left or right child is enough to determine 04173 // whether it is a leaf node or not. 04174 template <typename T> 04175 void ModelStrand<T>::CheckSelfCrossingsNextLevelRecursively ( 04176 BVHNode<T> * node1, BVHNode<T> * node2, 04177 Vector3<T> const & projectionDirection 04178 ) 04179 { 04180 CheckSelfCrossingsRecursively( node1, node2, projectionDirection ); 04181 if ( node1->Child(0) ) 04182 CheckSelfCrossingsNextLevelRecursively( node1->Child(0), node1->Child(1), projectionDirection ); 04183 if ( node2->Child(0) ) 04184 CheckSelfCrossingsNextLevelRecursively( node2->Child(0), node2->Child(1), projectionDirection ); 04185 } 04186 //----------------------------------------------------------------- 04187 // CheckSelfCrossingsRecursively 04188 // Assume no intersections between immediate adjacent links 04189 // Use the fact that the ids of sphere bvh leaf nodes are the same as 04190 // the link id and 04191 template <typename T> 04192 T ModelStrand<T>::CheckSelfCrossingsRecursively ( 04193 BVHNode<T> * node1, BVHNode<T> * node2, 04194 Vector3<T> const & projectionDirection 04195 ) 04196 { 04197 static T LinkDiameter = static_cast<T>(2.0) * m_tRadius; 04198 static T epsilon = m_tRadius * static_cast<T>(0.05); // for collision response 04199 //------------------------------------------------------------- 04200 if ( !node1->Child(0) && !node2->Child(0) && 04201 ( abs(node1->GetID() - node2->GetID()) == 1 ) ) 04202 { 04203 return DBL_MAX; 04204 } 04205 //------------------------------------------------------------- 04206 T overlap = TestOverlapCircle( node1, node2, projectionDirection ); 04207 //------------------------------------------------------------- 04208 if ( overlap < DBL_MIN ) { 04209 if ( node2->Child(0) == NULL ) { //&& node2->RightChild() == NULL ) { 04210 if ( node1->Child(0) ) { 04211 overlap = CheckSelfCrossingsRecursively( node1->Child(0), node2, projectionDirection ); 04212 } 04213 if ( node1->Child(1) ) { 04214 overlap = CheckSelfCrossingsRecursively( node1->Child(1), node2, projectionDirection ); 04215 } 04216 } 04217 else { 04218 if ( node2->Child(0) ) { 04219 overlap = TestOverlapCircle( node1, node2->Child(0), projectionDirection ); 04220 if ( overlap < DBL_MIN ) { 04221 if ( node1->Child(0) ) { 04222 overlap = CheckSelfCrossingsRecursively( node1->Child(0), node2->Child(0), projectionDirection ); 04223 } 04224 if ( node1->Child(1) ) { 04225 overlap = CheckSelfCrossingsRecursively( node1->Child(1), node2->Child(0), projectionDirection ); 04226 } 04227 } 04228 } 04229 if ( node2->Child(1) ) { 04230 overlap = TestOverlapCircle( node1, node2->Child(1), projectionDirection ); 04231 if ( overlap < DBL_MIN ) { 04232 if ( node1->Child(0) ) { 04233 overlap = CheckSelfCrossingsRecursively( node1->Child(0), node2->Child(1), projectionDirection ); 04234 } 04235 if ( node1->Child(1) ) { 04236 overlap = CheckSelfCrossingsRecursively( node1->Child(1), node2->Child(1), projectionDirection ); 04237 } 04238 } 04239 } 04240 } 04241 //--------------------------------------------------------- 04242 if ( node1->Child(0) == NULL && //node1->Child(1) == NULL && 04243 node2->Child(0) == NULL ) //&& node2->Child(1) == NULL ) 04244 { 04245 CheckCrossings( node1, node2, projectionDirection ); 04246 } 04247 } 04248 //------------------------------------------------------------- 04249 return overlap; 04250 } 04251 //----------------------------------------------------------------- 04252 template <typename T> 04253 T ModelStrand<T>::TestOverlapCircle ( 04254 BVHNode<T> * node1, BVHNode<T> * node2, 04255 Vector3<T> const & projectionDirection 04256 ) 04257 { 04258 Vector3<T> C1 = node1->GetCenter(); 04259 Vector3<T> C2 = node2->GetCenter(); 04260 04261 04262 C1.SetZ( 0 ); 04263 C2.SetZ( 0 ); 04264 return (C1 - C2).Length() - ( node1->GetRadius() + node2->GetRadius() ); 04265 } 04266 //----------------------------------------------------------------- 04267 template <typename T> 04268 void ModelStrand<T>::CheckCrossings ( 04269 BVHNode<T> * node1, BVHNode<T> * node2, 04270 Vector3<T> const & projectionDirection 04271 ) 04272 { 04273 int i = node1->GetID(); 04274 int j = node2->GetID(); 04275 04276 // Skip if a node is locked 04277 #ifdef TAPs_STRAND_LOCK_SEGMENTS 04278 if ( m_prIsLocked[i] ) return; 04279 if ( m_prIsLocked[j] ) return; 04280 #endif//TAPs_STRAND_LOCK_SEGMENTS 04281 04282 Matrix3x3<T> rotationMatrix = CGMath<T>::CreateRotationMatrix3x3FromVectorAtoVectorB( 04283 Vector3<T>( 0, 0, 1 ), projectionDirection ); 04284 04285 // Link# i 04286 Vector3<T> P1 = rotationMatrix * m_prVertex[i]; 04287 Vector3<T> P2 = rotationMatrix * m_prVertex[i+1]; 04288 // Link# j 04289 Vector3<T> Q1 = rotationMatrix * m_prVertex[j]; 04290 Vector3<T> Q2 = rotationMatrix * m_prVertex[j+1]; 04291 04292 // Project in z-direction 04293 Vector3<T> p1( P1[0], P1[1], 0 ); 04294 Vector3<T> p2( P2[0], P2[1], 0 ); 04295 Vector3<T> q1( Q1[0], Q1[1], 0 ); 04296 Vector3<T> q2( Q2[0], Q2[1], 0 ); 04297 04298 bool isTouched; 04299 T pt, qt; // parameter for the 1st & 2nd line 04300 // where intersection point = p1 + pt(p2-p1) 04301 // where intersection point = q1 + qt(q2-q1) 04302 CGMath<T>::FindIntersectionLineSegmentLineSegment( 04303 p1, p2, q1, q2, // I/P 04304 pt, qt, // O/P 04305 isTouched // O/P 04306 ); 04307 if ( 0 <= pt && pt <= 1 && 0 <= qt && qt <= 1 ) { 04308 Vector3<T> P = P1 + pt*( P2 - P1 ); 04309 Vector3<T> Q = Q1 + qt*( Q2 - Q1 ); 04310 04311 // i+1 and j+1 are for making the link# to be one-based instead of zero-based 04312 if ( P[2] > Q[2] ) { 04313 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04314 04315 #ifdef DEBUG_TOO 04316 int a = i*10 + m_iaCrossingCounters[i]++; 04317 int b = j*10 + m_iaCrossingCounters[j]++; 04318 InsertToList_TOO( -b, a ); 04319 InsertToList_TOO( a, b ); 04320 #endif//DEBUG_TOO 04321 04322 InsertToList( -(j), i ); 04323 InsertToList( +(i), j ); 04324 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04325 m_iaCrossingsForDowkerNotation[i] = -(j+1); // the link i is above the link j 04326 m_iaCrossingsForDowkerNotation[j] = +(i+1); // the link j is below the link i 04327 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04328 } 04329 else { 04330 #ifdef TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04331 04332 #ifdef DEBUG_TOO 04333 int a = i*10 + m_iaCrossingCounters[i]++; 04334 int b = j*10 + m_iaCrossingCounters[j]++; 04335 InsertToList_TOO( b, a ); 04336 InsertToList_TOO( -a, b ); 04337 #endif//DEBUG_TOO 04338 04339 InsertToList( +(j), i ); 04340 InsertToList( -(i), j ); 04341 #else //TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04342 m_iaCrossingsForDowkerNotation[i] = +(j+1); // the link j is above the link i 04343 m_iaCrossingsForDowkerNotation[j] = -(i+1); // the link i is below the link j 04344 #endif//TAPs_PROJECTION_ALLOWS_MULTIPLE_CONTACT_POINTS 04345 } 04346 } 04347 } 04348 //----------------------------------------------------------------- 04349 // END: Fns for CheckSelfCrossingForKnotRecognition function 04350 //================================================================= 04351 04352 //------------------------------------------------------------------- 04353 #endif//TAPs_ALLOW_SETTING_PROJECTION_DIRECTION 04354 //=================================================================== 04355 04356 04357 //------------------------------------------------------------------- 04358 #endif//TAPs_STRAND_KNOT_CONTROL_USE_DOWKER_NOTATION_VERSION_01 04359 //=================================================================== 04360 04361 04362 //----------------------------------------------------------------------------- 04363 #endif//TAPs_STRAND_KNOT_CONTROL 04364 //============================================================================= 04365 04366 04367 //============================================================================= 04368 #ifdef TAPs_USE_CUDA 04369 //----------------------------------------------------------------------------- 04370 template <typename T> 04371 bool ModelStrand<T>::CUDA_Initialize_All () 04372 { 04373 bool result = true; 04374 if ( !CUDA_Initialize_VertexList() ) result = false; 04375 if ( !CUDA_Initialize_PrevVertexList() ) result = false; 04376 04377 #ifdef TAPs_ADVANCED_SIMULATION 04378 if ( !CUDA_Initialize_SimFlagsList() ) result = false; 04379 if ( !CUDA_Initialize_PosConstraintList() ) result = false; 04380 #endif//TAPs_ADVANCED_SIMULATION 04381 04382 //std::cout << "m_cudaID: " << m_cudaID << "\n"; 04383 04384 #ifdef TAPs_ADVANCED_SIMULATION 04385 TAPs::CUDA::InitailizeDataForSutureModel_ADVSIM( 04386 m_cudaID, 04387 m_iNoLinks+1, 04388 m_cudaVertexList, 04389 m_cudaPrevVertexList, 04390 m_cudaSimFlagsList, 04391 m_cudaPosConstraintList 04392 ); 04393 #else //TAPs_ADVANCED_SIMULATION 04394 TAPs::CUDA::InitailizeDataForSutureModel( 04395 m_cudaID, 04396 m_iNoLinks+1, 04397 m_cudaVertexList, 04398 m_cudaPrevVertexList 04399 ); 04400 #endif//TAPs_ADVANCED_SIMULATION 04401 04402 //std::cout << "m_cudaID: " << m_cudaID << "\n"; 04403 04404 return result; 04405 } 04406 04407 template <typename T> 04408 bool ModelStrand<T>::CUDA_Initialize_VertexList () 04409 { 04410 CUDA_Cleanup_VertexList(); 04411 04412 std::cout << "m_cudaVertexList size: " << (m_iNoLinks+1) * 4 << "\n"; 04413 04414 unsigned int size = sizeof(float) * (m_iNoLinks+1) * 4; 04415 04416 // Vertex List 04417 m_cudaVertexList = (float *)malloc( size ); 04418 if ( m_cudaVertexList ) { 04419 for ( unsigned int i = 0, p = 0; i <= static_cast<unsigned int>( m_iNoLinks ); ++i ) { 04420 m_cudaVertexList[p++] = m_prVertex[i][0]; 04421 m_cudaVertexList[p++] = m_prVertex[i][1]; 04422 m_cudaVertexList[p++] = m_prVertex[i][2]; 04423 m_cudaVertexList[p++] = 1; 04424 } 04425 } 04426 else { 04427 std::cout << "ERROR: Could not allocate memory for (Suture Model) CUDA!" << std::endl; 04428 exit( -1 ); 04429 } 04430 04431 return true; 04432 } 04433 04434 template <typename T> 04435 bool ModelStrand<T>::CUDA_Initialize_PrevVertexList () 04436 { 04437 CUDA_Cleanup_PrevVertexList(); 04438 04439 std::cout << "m_cudaPrevVertexList size: " << (m_iNoLinks+1) * 4 << "\n"; 04440 04441 unsigned int size = sizeof(float) * (m_iNoLinks+1) * 4; 04442 04443 // Previous Vertex List 04444 m_cudaPrevVertexList = (float *)malloc( size ); 04445 if ( m_cudaPrevVertexList ) { 04446 CUDA_CopyPrevVertexToMem(); 04447 } 04448 else { 04449 std::cout << "ERROR: Could not allocate memory for (Previous Vertex List) CUDA!" << std::endl; 04450 exit( -1 ); 04451 } 04452 04453 return true; 04454 } 04455 04456 template <typename T> 04457 void ModelStrand<T>::CUDA_Cleanup_All () 04458 { 04459 CUDA_Cleanup_VertexList(); 04460 CUDA_Cleanup_PrevVertexList(); 04461 04462 #ifdef TAPs_ADVANCED_SIMULATION 04463 CUDA_Cleanup_SimFlagsList(); 04464 CUDA_Cleanup_PosConstraintList(); 04465 #endif//TAPs_ADVANCED_SIMULATION 04466 } 04467 04468 template <typename T> 04469 void ModelStrand<T>::CUDA_Cleanup_VertexList () 04470 { 04471 if ( m_cudaVertexList ) { 04472 free( m_cudaVertexList ); 04473 m_cudaVertexList = NULL; 04474 } 04475 } 04476 04477 template <typename T> 04478 void ModelStrand<T>::CUDA_Cleanup_PrevVertexList () 04479 { 04480 if ( m_cudaPrevVertexList ) { 04481 free( m_cudaPrevVertexList ); 04482 m_cudaPrevVertexList = NULL; 04483 } 04484 } 04485 04486 template <typename T> 04487 void ModelStrand<T>::CUDA_CopyVertexToMem () 04488 { 04489 if ( !m_cudaVertexList ) return; 04490 for ( unsigned int i = 0, p = 0; i <= static_cast<unsigned int>( m_iNoLinks ); ++i ) { 04491 m_cudaVertexList[p++] = m_prVertex[i][0]; 04492 m_cudaVertexList[p++] = m_prVertex[i][1]; 04493 m_cudaVertexList[p++] = m_prVertex[i][2]; 04494 //m_cudaVertexList[p++] = 1; 04495 if ( GetFixStatusOfPtNo( i ) ) m_cudaVertexList[p++] = 0; // the point is fixed 04496 else m_cudaVertexList[p++] = 1; // the point is not fixed 04497 } 04498 } 04499 04500 template <typename T> 04501 void ModelStrand<T>::CUDA_CopyPrevVertexToMem () 04502 { 04503 if ( !m_cudaPrevVertexList ) return; 04504 for ( unsigned int i = 0, p = 0; i <= static_cast<unsigned int>( m_iNoLinks ); ++i ) { 04505 //* 04506 m_cudaPrevVertexList[p++] = m_prVertexPrevPos[i][0]; 04507 m_cudaPrevVertexList[p++] = m_prVertexPrevPos[i][1]; 04508 m_cudaPrevVertexList[p++] = m_prVertexPrevPos[i][2]; 04509 m_cudaPrevVertexList[p++] = 1; 04510 //*/ 04511 04512 /* 04513 m_cudaPrevVertexList[p++] = m_prVertex[i][0]; 04514 m_cudaPrevVertexList[p++] = m_prVertex[i][1]; 04515 m_cudaPrevVertexList[p++] = m_prVertex[i][2]; 04516 m_cudaPrevVertexList[p++] = 1; 04517 //*/ 04518 } 04519 } 04520 04521 template <typename T> 04522 void ModelStrand<T>::CUDA_CopyMemToVertex () 04523 { 04524 if ( !m_cudaVertexList ) return; 04525 for ( unsigned int i = 0, p = 0; i <= static_cast<unsigned int>( m_iNoLinks ); ++i ) { 04526 m_prVertex[i].SetXYZ( 04527 m_cudaVertexList[p ], 04528 m_cudaVertexList[p+1], 04529 m_cudaVertexList[p+2] 04530 ); 04531 p += 4; 04532 } 04533 } 04534 04535 template <typename T> 04536 void ModelStrand<T>::CUDA_CopyMemToPrevVertex () 04537 { 04538 if ( !m_cudaPrevVertexList ) return; 04539 for ( unsigned int i = 0, p = 0; i <= static_cast<unsigned int>( m_iNoLinks ); ++i ) { 04540 m_prVertexPrevPos[i].SetXYZ( 04541 m_cudaPrevVertexList[p ], 04542 m_cudaPrevVertexList[p+1], 04543 m_cudaPrevVertexList[p+2] 04544 ); 04545 p += 4; 04546 } 04547 } 04548 04549 //----------------------------------------------------------------------------- 04550 #ifdef TAPs_ADVANCED_SIMULATION 04551 //----------------------------------------------------------------------------- 04552 template <typename T> 04553 bool ModelStrand<T>::CUDA_Initialize_SimFlagsList () 04554 { 04555 CUDA_Cleanup_SimFlagsList(); 04556 04557 std::cout << "m_cudaSimFlagsList size: " << (m_iNoLinks+1) << "\n"; 04558 04559 unsigned int size = sizeof(unsigned int) * (m_iNoLinks+1); 04560 04561 // Sim Flags List 04562 m_cudaSimFlagsList = (unsigned int *)malloc( size ); 04563 if ( m_cudaSimFlagsList ) { 04564 CUDA_CopySimFlagsToMem(); 04565 } 04566 else { 04567 std::cout << "ERROR: Could not allocate memory for (Suture Model) CUDA!" << std::endl; 04568 exit( -1 ); 04569 } 04570 04571 return true; 04572 } 04573 template <typename T> 04574 bool ModelStrand<T>::CUDA_Initialize_PosConstraintList () 04575 { 04576 CUDA_Cleanup_PosConstraintList(); 04577 04578 std::cout << "m_cudaPosConstraintList size: " << (m_iNoLinks+1) * 4 << "\n"; 04579 04580 unsigned int size = sizeof(float) * (m_iNoLinks+1) * 4; 04581 04582 // Position Constraint List 04583 m_cudaPosConstraintList = (float *)malloc( size ); 04584 if ( m_cudaPosConstraintList ) { 04585 CUDA_CopyPosConstraintToMem(); 04586 } 04587 else { 04588 std::cout << "ERROR: Could not allocate memory for (Suture Model) CUDA!" << std::endl; 04589 exit( -1 ); 04590 } 04591 04592 return true; 04593 } 04594 template <typename T> 04595 void ModelStrand<T>::CUDA_Cleanup_SimFlagsList () 04596 { 04597 if ( m_cudaSimFlagsList ) { 04598 free( m_cudaSimFlagsList ); 04599 m_cudaSimFlagsList = NULL; 04600 } 04601 } 04602 template <typename T> 04603 void ModelStrand<T>::CUDA_Cleanup_PosConstraintList () 04604 { 04605 if ( m_cudaPosConstraintList ) { 04606 free( m_cudaPosConstraintList ); 04607 m_cudaPosConstraintList = NULL; 04608 } 04609 } 04610 template <typename T> 04611 void ModelStrand<T>::CUDA_CopySimFlagsToMem () 04612 { 04613 if ( !m_cudaSimFlagsList ) return; 04614 04615 for ( unsigned int i = 0; i <= static_cast<unsigned int>( m_iNoLinks ); ++i ) { 04616 m_cudaSimFlagsList[i] = m_SimFlags[i].GetSimulationConstraints().FlagsToUnsignedInt(); 04617 } 04618 } 04619 template <typename T> 04620 void ModelStrand<T>::CUDA_CopyPosConstraintToMem () 04621 { 04622 if ( !m_cudaPosConstraintList ) return; 04623 04624 AdvSimSupport_DS<T> * pSimData = AdvSimSupport<T>::GetAdvSimData(); 04625 std::vector< AdvSimSupport_DS_InteractionSutureAndModel<T> > * pDataInteractionSutureAndModel = &( pSimData->GetInteractionSutureAndModel( AdvSimID ) ); 04626 for ( unsigned int k = 0; k < static_cast<unsigned int>( pDataInteractionSutureAndModel->size() ); ++k ) { 04627 unsigned int idx = 4 * (*pDataInteractionSutureAndModel)[k].VertexIDSuture; 04628 // Position constraint 04629 m_cudaPosConstraintList[idx++] = (*pDataInteractionSutureAndModel)[k].VertexModel->GetPosition()[0]; 04630 m_cudaPosConstraintList[idx++] = (*pDataInteractionSutureAndModel)[k].VertexModel->GetPosition()[1]; 04631 m_cudaPosConstraintList[idx++] = (*pDataInteractionSutureAndModel)[k].VertexModel->GetPosition()[2]; 04632 // Force ratio 04633 m_cudaPosConstraintList[idx++] = (*pDataInteractionSutureAndModel)[k].ForceRatio; 04634 } 04635 } 04636 template <typename T> 04637 void ModelStrand<T>::CUDA_CopyMemToSimFlags () 04638 { 04639 if ( !m_cudaSimFlagsList ) return; 04640 04641 for ( unsigned int i = 0; i <= static_cast<unsigned int>( m_iNoLinks ); ++i ) { 04642 m_SimFlags[i].GetSimulationConstraints() = m_cudaSimFlagsList[i]; 04643 } 04644 } 04645 template <typename T> 04646 void ModelStrand<T>::CUDA_CopyMemToPosConstraint () 04647 { 04648 if ( !m_cudaPosConstraintList ) return; 04649 04650 AdvSimSupport_DS<T> * pSimData = AdvSimSupport<T>::GetAdvSimData(); 04651 std::vector< AdvSimSupport_DS_InteractionSutureAndModel<T> > * pDataInteractionSutureAndModel = &( pSimData->GetInteractionSutureAndModel( AdvSimID ) ); 04652 for ( unsigned int k = 0; k < static_cast<unsigned int>( pDataInteractionSutureAndModel->size() ); ++k ) { 04653 int vertexID = (*pDataInteractionSutureAndModel)[k].VertexIDSuture; 04654 unsigned int idx = 4 * vertexID; 04655 T forceRatio = m_cudaPosConstraintList[idx+3]; 04656 04657 std::cout << "Suture Vertex Sim Flags# " << vertexID << ":\t" << m_SimFlags[vertexID] << " " << m_SimFlags[vertexID].GetSimulationConstraints() << "\n"; 04658 std::cout << "Constraint VertexID: " << vertexID << "" << "\tForceRatio: " << forceRatio << "\n"; 04659 04660 // SHIFTING OF SUTURE DUE TO SLIPDABLE CONSTRAINTS 04661 // Since AdvSimSupport_DS_InteractionSutureAndModel class contains 04662 //unsigned int VertexIDSuture; //!< vertex ID of suture 04663 //DS::SimulationFlags * SimFlagsSuture; //!< simulation flags of suture Vector3<T> * VertexSuture; //!< vertex of suture 04664 //Vector3<T> * VertexSuture; //!< a vertex of suture 04665 //HEVertex<T> * VertexModel; //!< vertex of model 04666 //T ForceRatio; //!< force ratio [0-1] (1 means suture's vertex completely dominates model's) 04667 // So VertexIDSuture, 7SimFlagsSuture, and &VertexSuture have to be updated! 04668 04669 // The shift values are encoded in forceRatio. 04670 04671 // Shift up 04672 if ( forceRatio > TAPs_Const_Check_Suture_ShiftUp ) { 04673 // Shift up 04674 if ( vertexID < GetNumberOfLinks() ) { 04675 //m_SimFlags[vertexID+1] = m_SimFlags[vertexID]; 04676 04677 /* 04678 std::cout << "m_SimFlags[vertexID+1]: " << m_SimFlags[vertexID+1] << "\n"; 04679 if ( m_SimFlags[vertexID+1].CheckSimulationConstraints( TAPs::Enum::AddOn::CLEARED ) ) { 04680 std::cout << "CLEARED\n"; 04681 } 04682 else { 04683 std::cout << "NOT CLEARED\n"; 04684 } 04685 //*/ 04686 04687 04688 if ( m_SimFlags[vertexID+1].AreSimulationFlagsCleared() ) { 04689 m_SimFlags[vertexID+1].SetSimulationConstraints( TAPs::Enum::AddOn::SLIDABLE ); 04690 m_SimFlags[vertexID].ClearSimulationConstraints( TAPs::Enum::AddOn::SLIDABLE ); 04691 ++((*pDataInteractionSutureAndModel)[k].VertexIDSuture); 04692 04693 //std::cout << "Shift up: " << "VertexID: " << vertexID 04694 // << " Prev #id: " << (*pDataInteractionSutureAndModel)[k].VertexIDSuture - 1 04695 // << " New #id: " << (*pDataInteractionSutureAndModel)[k].VertexIDSuture 04696 // << " sim flags of # " << vertexID << ": " << m_SimFlags[vertexID] 04697 // << " sim flags of # " << vertexID+1 << ": " << m_SimFlags[vertexID+1] << "\n"; 04698 04699 // Position constraint 04700 (*pDataInteractionSutureAndModel)[k].VertexModel->SetPosition( m_cudaPosConstraintList[idx], m_cudaPosConstraintList[idx+1], m_cudaPosConstraintList[idx+2] ); 04701 // Force ratio 04702 (*pDataInteractionSutureAndModel)[k].ForceRatio = forceRatio - TAPs_Const_Suture_ShiftUp; 04703 // Ptr to Suture Vertex 04704 (*pDataInteractionSutureAndModel)[k].VertexSuture = &m_prVertex[vertexID+1]; 04705 // Ptr to Suture SimFlag 04706 (*pDataInteractionSutureAndModel)[k].SimFlagsSuture = &m_SimFlags[vertexID+1]; 04707 } 04708 else { 04709 // Force ratio 04710 (*pDataInteractionSutureAndModel)[k].ForceRatio = forceRatio - TAPs_Const_Suture_ShiftUp; 04711 } 04712 } 04713 } 04714 // Shift down 04715 else if ( forceRatio > TAPs_Const_Check_Suture_ShiftDown ) { 04716 // Shift down 04717 if ( vertexID > 0 ) { 04718 //m_SimFlags[vertexID-1] = m_SimFlags[vertexID]; 04719 04720 if ( m_SimFlags[vertexID-1].AreSimulationFlagsCleared() ) { 04721 m_SimFlags[vertexID-1].SetSimulationConstraints( TAPs::Enum::AddOn::SLIDABLE ); 04722 m_SimFlags[vertexID].ClearSimulationConstraints( TAPs::Enum::AddOn::SLIDABLE ); 04723 --((*pDataInteractionSutureAndModel)[k].VertexIDSuture); 04724 04725 //std::cout << "Shift down: " << "VertexID: " << vertexID 04726 // << " Prev #id: " << (*pDataInteractionSutureAndModel)[k].VertexIDSuture + 1 04727 // << " New #id: " << (*pDataInteractionSutureAndModel)[k].VertexIDSuture 04728 // << " sim flags of # " << vertexID << ": " << m_SimFlags[vertexID] 04729 // << " sim flags of # " << vertexID-1 << ": " << m_SimFlags[vertexID-1] << "\n"; 04730 04731 // Position constraint 04732 (*pDataInteractionSutureAndModel)[k].VertexModel->SetPosition( m_cudaPosConstraintList[idx], m_cudaPosConstraintList[idx+1], m_cudaPosConstraintList[idx+2] ); 04733 // Force ratio 04734 (*pDataInteractionSutureAndModel)[k].ForceRatio = forceRatio - TAPs_Const_Suture_ShiftDown; 04735 // Ptr to Suture Vertex 04736 (*pDataInteractionSutureAndModel)[k].VertexSuture = &m_prVertex[vertexID-1]; 04737 // Ptr to Suture SimFlag 04738 (*pDataInteractionSutureAndModel)[k].SimFlagsSuture = &m_SimFlags[vertexID-1]; 04739 } 04740 else { 04741 // Force ratio 04742 (*pDataInteractionSutureAndModel)[k].ForceRatio = forceRatio - TAPs_Const_Suture_ShiftDown; 04743 } 04744 } 04745 } 04746 else // NO SHIFT 04747 { 04748 // Position constraint 04749 (*pDataInteractionSutureAndModel)[k].VertexModel->SetPosition( m_cudaPosConstraintList[idx], m_cudaPosConstraintList[idx+1], m_cudaPosConstraintList[idx+2] ); 04750 // Force ratio 04751 (*pDataInteractionSutureAndModel)[k].ForceRatio = forceRatio; 04752 } 04753 } 04754 } 04755 //----------------------------------------------------------------------------- 04756 #endif//TAPs_ADVANCED_SIMULATION 04757 //----------------------------------------------------------------------------- 04758 04759 template <typename T> 04760 void ModelStrand<T>::CUDA_SwapBuffers () 04761 { 04762 float * tmpPtr = m_cudaVertexList; 04763 m_cudaVertexList = m_cudaPrevVertexList; 04764 m_cudaPrevVertexList = tmpPtr; 04765 04766 Vector3<T> * tmpPtrV = m_prVertex; 04767 m_prVertex = m_prVertexPrevPos; 04768 m_prVertexPrevPos = tmpPtrV; 04769 } 04770 04771 //----------------------------------------------------------------------------- 04772 #endif//TAPs_USE_CUDA 04773 //============================================================================= 04774 04775 04776 //----------------------------------------------------------------------------- 04777 //============================================================================= 04778 END_NAMESPACE_TAPs__OpenGL 04779 //----------------------------------------------------------------------------- 04780 //345678901234567890123456789012345678901234567890123456789012345678901234567890 04781 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8