![]() |
TAPs 0.7.7.3
|
00001 /****************************************************************************** 00002 TAPsModelElasticRod.cpp 00003 ******************************************************************************/ 00007 /****************************************************************************** 00008 SUKITTI PUNAK (07/07/2009) 00009 UPDATE (03/21/2011) 00010 ******************************************************************************/ 00011 #include "TAPsModelElasticRod.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 00017 //============================================================================= 00018 template <typename T> int ModelElasticRod<T>::g_NumOfElasticRods = 0; 00019 //template <typename T> bool ModelElasticRod<T>::g_IsGLSLInit = false; 00020 //----------------------------------------------------------------------------- 00021 // Constructor 00022 template <typename T> 00023 ModelElasticRod<T>::ModelElasticRod ( 00024 int iNoLinks, // # of links/segments 00025 T tRadius, // radius 00026 T tTotalLength, // total length 00027 T tTotalMass, // total mass 00028 Vector3<T> & posOfVertex0, // position of the 1st node 00029 ShapeInitializationParameters ShapeParameters // initialization parameters for shape 00030 00031 #ifdef TAPs_USE_CUDA 00032 , bool bUseCUDAsPLHM // utilizing CUDA's page-locked host memory 00033 #endif//TAPs_USE_CUDA 00034 ) : 00035 IdxCurr(0), IdxPrev(1), IdxNext(IdxPrev), // for data accessing 00036 m_vStartPos( posOfVertex0 ), // the position of the first point 00037 00038 // For drawing by OpenGL 00039 #if defined(__gl_h_) || defined(__GL_H__) 00040 m_GLVertexArray( 0 ), 00041 m_drawNV( 8 ), 00042 m_drawCrossSectionVertices( NULL ), 00043 m_drawCrossSectionNormals( NULL ), 00044 m_drawCrossSectionTexCoords( NULL ), 00045 vertices( NULL ), 00046 normals( NULL ), 00047 texCoords( NULL ), 00048 sVertices( NULL ), 00049 m_pVertexData( NULL ) 00050 #endif//defined(__gl_h_) || defined(__GL_H__) 00051 00052 { 00053 m_Parameters.NumOfNodes = iNoLinks+1; 00054 m_Parameters.Radius = tRadius; 00055 m_Parameters.TotalLength = tTotalLength; 00056 m_Parameters.TotalMass = tTotalMass; 00057 00058 m_Parameters.Kstretch_modulus = 5000; 00059 m_Parameters.Kbend_modulus = 250; 00060 m_Parameters.Kshear_modulus = 250; 00061 00062 m_Parameters.Ps=1; 00063 m_Parameters.Pb[0]=m_Parameters.Pb[1]=m_Parameters.Pb[2]=0; 00064 m_Parameters.Kt=0; 00065 m_Parameters.Kr[0]=m_Parameters.Kr[1]=m_Parameters.Kr[2]=0; 00066 m_Parameters.Dt=0; 00067 m_Parameters.Dr[0]=m_Parameters.Dr[1]=m_Parameters.Dr[2]=0; 00068 m_Parameters.Kconstraint_3rdDirAlignTangent=0.5; 00069 m_Parameters.Kvdamping=0.9; 00070 m_Parameters.MaterialDensity = m_Parameters.TotalMass / ( m_Parameters.Radius * m_Parameters.Radius * Math<T>::PI * m_Parameters.TotalLength ); 00071 00072 m_Parameters.Kgravity = -9.81; 00073 #ifdef TAPs_ADD_RESTING_LEVEL_Y 00074 m_Parameters.RestingLevel = -1000.0; 00075 #endif//TAPs_ADD_RESTING_LEVEL_Y 00076 00077 // For collision detection 00078 m_Parameters.KselfCDR = 0.15; 00079 m_Parameters.KselfStick = 0.05; 00080 m_Parameters.K_CDRwBV_Cylinder = 1; 00081 m_Parameters.K_CDRwBV_Sphere = 0.01; 00082 m_Parameters.K_CDRwTriangle = 1; 00083 // Offsets 00084 m_Parameters.Offset_CD_Self = 0;//m_Parameters.Radius/2; 00085 m_Parameters.Offset_CD_Triangle = m_Parameters.Radius/2; 00086 m_Parameters.Offset_CD_BV_Sphere = m_Parameters.Radius/2; 00087 m_Parameters.Offset_CD_BV_Cylinder = m_Parameters.Radius/2; 00088 00089 // For collision detection with implicit objects 00090 m_Parameters.K_CDRwImpObj_Sphere = 1; 00091 m_Parameters.K_CDRwImpObj_Torus = 1; 00092 m_Parameters.Offset_CD_ImpObj_Sphere = m_Parameters.Radius/2; 00093 m_Parameters.Offset_CD_ImpObj_Torus = m_Parameters.Radius/2; 00094 00095 SetMaterialProperties( m_Parameters.Kstretch_modulus, m_Parameters.Kbend_modulus, m_Parameters.Kshear_modulus, m_Parameters.MaterialDensity ); 00096 00097 #if defined(__gl_h_) || defined(__GL_H__) 00098 InitGL(); 00099 #endif 00100 00101 // Initialize the elastic rod's configuration 00102 InitShapeParameters = ShapeParameters; 00103 Initialize( InitShapeParameters.StartShape ); 00104 00105 // Initialize collision detection unit 00106 m_CD.CreateCD( &IdxCurr, &IdxNext, &m_Parameters, &m_Nodes ); 00107 00108 // Initialize CUDA for computation 00109 #ifdef TAPs_USE_CUDA 00110 try { 00111 //m_Parameters.EnableCUDA = true; 00112 m_CUDA.CreateCUDA( &IdxCurr, &IdxPrev, &IdxNext, &m_Parameters, &m_Nodes, bUseCUDAsPLHM ); 00113 } 00114 catch ( char * e ) { 00115 std::cout << e << std::endl; 00116 exit(-1); 00117 } 00118 #endif//TAPs_USE_CUDA 00119 00120 // Initialize knot recognition unit 00121 #ifdef TAPs_ADD_KNOT_RECOGNITION 00122 unsigned char numOfKnotAllowed = 8; 00123 m_KR.CreateKR( &IdxCurr, &IdxNext, &m_Parameters, &m_Nodes, m_CD.GetBVHTree(), numOfKnotAllowed ); 00124 #endif//TAPs_ADD_KNOT_RECOGNITION 00125 00126 // Assign an ID for this elastic rod and count the number of created elastic rods 00127 m_ID = g_NumOfElasticRods++; 00128 00129 00130 // Set all point to slidable 00131 for ( int i = 0; i < GetNumberOfPoints(); ++i ) { 00132 GetListOfNodes()[i].SimFlags.SetSimulationConstraints( TAPs::Enum::AddOn::SLIDABLE ); 00133 } 00134 } 00135 00136 00137 // Destructor 00138 template <typename T> 00139 ModelElasticRod<T>::~ModelElasticRod () 00140 { 00141 #if defined(__gl_h_) || defined(__GL_H__) 00142 ClearGL(); 00143 #endif 00144 } 00145 00146 00147 // Destructor 00148 template <typename T> 00149 ModelElasticRod<T> * ModelElasticRod<T>::CopySegment ( int startLink, int endLink ) 00150 { 00151 if ( startLink > endLink ) return NULL; 00152 if ( startLink < 0 ) startLink = 0; 00153 if ( endLink > GetNumberOfLinks()-1 ) endLink = GetNumberOfLinks()-1; 00154 00155 int iNoLinks = endLink - startLink + 1; 00156 T ratio = static_cast<T>( iNoLinks ) / GetNumberOfLinks(); 00157 T tTotalLength = GetTotalLength() / ratio; 00158 T tTotalMass = GetTotalMass() / ratio; 00159 ModelElasticRod<T> * pER = new ModelElasticRod( 00160 iNoLinks, 00161 GetRadius(), 00162 tTotalLength, 00163 tTotalMass 00164 ); 00165 00166 // Copy the parameter properties 00167 pER->m_Parameters = m_Parameters; 00168 pER->m_Parameters.NumOfNodes = iNoLinks + 1; 00169 pER->m_Parameters.TotalLength = tTotalLength; 00170 pER->m_Parameters.TotalMass = tTotalMass; 00171 00172 // Copy the shape and simulation properties 00173 SetOfElasticRodNodes::const_iterator orig = GetListOfNodes().begin(); 00174 SetOfElasticRodNodes::iterator dest = pER->GetListOfNodes().begin(); 00175 int c = 0; 00176 while ( c < startLink ) { 00177 ++orig; 00178 ++c; 00179 } 00180 00181 for ( ; c <= endLink+1; ++c ) { 00182 *dest = *orig; 00183 ++orig; 00184 ++dest; 00185 } 00186 00187 return pER; 00188 } 00189 00190 00191 // Return this object info as a string 00192 template <typename T> 00193 std::string ModelElasticRod<T>::StrInfo () const 00194 { 00195 std::stringstream output; 00196 output << "Pointer: " << this << "\t" 00197 << "TAPs::ModelElasticRod<" 00198 << typeid(T).name() << "> Class:"; 00199 //------------------------------------------------- 00200 output << "\n\tLength: " << m_Parameters.TotalLength 00201 << "\n\tRadius: " << m_Parameters.Radius 00202 << "\n\tMass: " << m_Parameters.TotalMass 00203 << "\n\tSimulation Info:" 00204 << "\n\t\tnumber of Links is " << m_Parameters.NumOfNodes-1 << " where each link's length is " << m_Parameters.LinkLength 00205 << "\n\t\tstretch modulus (Es): " << m_Parameters.Kstretch_modulus 00206 << "\n\t\tbend modulus (Eb): " << m_Parameters.Kbend_modulus 00207 << "\n\t\tshear modulus (G): " << m_Parameters.Kshear_modulus 00208 << "\n\t\tmaterial density: " << m_Parameters.MaterialDensity 00209 << "\n\t\tpotential stretch constant (Ps): " << m_Parameters.Ps << " (Ps = Es*pi*r^2)" 00210 << "\n\t\tpotential bend constant (Pb): " << m_Parameters.Pb[0] << " " << m_Parameters.Pb[1] << " " << m_Parameters.Pb[2] 00211 << " (Pb[0] = Pb[1] = Eb*pi*r^2*0.25; Pb[2] = G*pi*r^2*0.5)" 00212 << "\n\t\tkinetic translational constant (Kt): " << m_Parameters.Kt 00213 << "\n\t\tkinetic rotational constant (Kr): " << m_Parameters.Kr[0] << " " << m_Parameters.Kr[1] << " " << m_Parameters.Kr[2] 00214 << "\n\t\ttranslational dissipation constant (Dt): " << m_Parameters.Dt 00215 << "\n\t\trotational dissipation constant (Dr): " << m_Parameters.Dr[0] << " " << m_Parameters.Dr[1] << " " << m_Parameters.Dr[2] 00216 << "\n\t\tconstaint constant (Kconstraint_3rdDirAlignTangent): " << m_Parameters.Kconstraint_3rdDirAlignTangent 00217 << "\n\t\tvelocity damping constant (Kvdamping): " << m_Parameters.Kvdamping 00218 << "\n"; 00219 00220 return output.str(); 00221 } 00222 00223 // Get the stretch Young's modulus 00224 template <typename T> 00225 T ModelElasticRod<T>::GetStretchModulus () const 00226 { 00227 return m_Parameters.Kstretch_modulus; 00228 } 00229 00230 // Set the stretch Young's modulus 00231 template <typename T> 00232 void ModelElasticRod<T>::SetStretchModulus ( T k ) 00233 { 00234 m_Parameters.Kstretch_modulus = k; 00235 m_Parameters.Ps = m_Parameters.Kstretch_modulus * Math<T>::PI * m_Parameters.Radius*m_Parameters.Radius; 00236 } 00237 00238 // Get the bend Young's modulus 00239 template <typename T> 00240 T ModelElasticRod<T>::GetBendModulus () const 00241 { 00242 return m_Parameters.Kbend_modulus; 00243 } 00244 00245 // Set the bend Young's modulus 00246 template <typename T> 00247 void ModelElasticRod<T>::SetBendModulus ( T k ) 00248 { 00249 m_Parameters.Kbend_modulus = k; 00250 m_Parameters.Pb[0] = m_Parameters.Pb[1] = m_Parameters.Kbend_modulus * Math<T>::PI * m_Parameters.Radius*m_Parameters.Radius * 0.25; 00251 } 00252 00253 // Get the shear modulus 00254 template <typename T> 00255 T ModelElasticRod<T>::GetShearModulus () const 00256 { 00257 return m_Parameters.Kshear_modulus; 00258 } 00259 00260 // Set the shear modulus 00261 template <typename T> 00262 void ModelElasticRod<T>::SetShearModulus ( T k ) 00263 { 00264 m_Parameters.Kshear_modulus = k; 00265 m_Parameters.Pb[2] = m_Parameters.Kshear_modulus * Math<T>::PI * m_Parameters.Radius*m_Parameters.Radius * 0.5; 00266 } 00267 00268 // Get the material density 00269 template <typename T> 00270 T ModelElasticRod<T>::GetMaterialDensity () const 00271 { 00272 return m_Parameters.MaterialDensity; 00273 } 00274 00275 // Set the material density 00276 template <typename T> 00277 void ModelElasticRod<T>::SetMaterialDensity ( T material_density ) 00278 { 00279 m_Parameters.MaterialDensity = material_density; 00280 } 00281 00282 // Set the elastic rod's material properties 00283 template <typename T> 00284 void ModelElasticRod<T>::SetMaterialProperties ( 00285 T stretch_modulus, T bend_modulus, T shear_modulus, T material_density ) 00286 { 00287 SetStretchModulus( stretch_modulus ); 00288 SetBendModulus( bend_modulus ); 00289 SetShearModulus( shear_modulus ); 00290 SetMaterialDensity( material_density ); 00291 } 00292 00293 // Initialize 00294 template <typename T> 00295 void ModelElasticRod<T>::Initialize ( enum ShapeInitializationParameters::Shape shape ) throw(...) 00296 { 00297 // Set the number of elastic rod nodes 00298 try { 00299 m_Nodes.resize( m_Parameters.NumOfNodes ); 00300 } 00301 catch ( std::bad_alloc & e ) { 00302 std::cerr << StrInfo() << " couldn't allocate the elastic rod of node size: " << m_Parameters.NumOfNodes 00303 << "[" << e.what() << "]" << std::endl; 00304 throw( e ); 00305 } 00306 00307 InitializeElasticRodNodes( shape ); 00308 } 00309 00310 // Initialize both centerlines and orientations 00311 template <typename T> 00312 void ModelElasticRod<T>::InitializeElasticRodNodes ( enum ShapeInitializationParameters::Shape shape ) 00313 { 00314 m_Parameters.MassOfPoint = m_Parameters.TotalMass / (m_Parameters.NumOfNodes); 00315 m_Parameters.LinkLength = m_Parameters.TotalLength / (m_Parameters.NumOfNodes-1); 00316 00317 //Vector3<T> position = m_vStartPos; 00318 00319 // 00320 // SET A STRAIGHT LINE -- for centerlines 00321 // 00322 if ( shape == ShapeInitializationParameters::STRAIGHT_SHAPE ) { 00323 unsigned int id = 0; 00324 Vector3<T> position( m_vStartPos ); 00325 //Vector3<T> offsetPos( m_vStartPos - position ); 00326 Vector3<T> offset( -m_Parameters.LinkLength, 0, 0 ); 00327 00328 //position += offset; // need this, otherwise runtime error with "w.exe > t.txt" 00329 00330 SetOfElasticRodNodes::iterator it = m_Nodes.begin(); 00331 while ( it != m_Nodes.end() ) { 00332 it->ID = id++; // assign id to the node 00333 it->Centerline[IdxCurr].SetMass( m_Parameters.MassOfPoint ); 00334 it->Centerline[IdxCurr].SetSize( m_Parameters.Radius ); 00335 it->Centerline[IdxCurr].SetPosition( position ); 00336 00337 it->CenterlineRestLength = m_Parameters.LinkLength; 00338 00339 //std::cout << "it->CenterlineRestLength: " << it->CenterlineRestLength << "\n"; 00340 00341 position += offset; 00342 it->Centerline[IdxPrev] = it->Centerline[IdxCurr]; // Initialize the previous centerline 00343 ++it; 00344 } 00345 } 00346 // 00347 // SET A HELIX -- for centerlines 00348 // 00349 else if ( shape == ShapeInitializationParameters::HELIX_SHAPE ) { 00350 unsigned int id = 0; 00351 T a = InitShapeParameters.Helix_Radius; // helix radius 00352 T b = InitShapeParameters.Helix_Pitch; // pitch := 2*pi*b 00353 T t = 0.0; 00354 Vector3<T> position( a*cos(t), a*sin(t), b*t ); 00355 Vector3<T> offsetPos( m_vStartPos - position ); 00356 position += offsetPos; 00357 00358 // Find the parameter value that make the next point close to the link length 00359 T errThreshold = 1E-6; 00360 T linkLenMax = m_Parameters.LinkLength + errThreshold; 00361 T linkLenMin = m_Parameters.LinkLength - errThreshold; 00362 T prevMaxS = 100; 00363 T prevMinS = 0; 00364 T s; 00365 00366 //std::cout << "linkLenMax: " << linkLenMax << "\n"; 00367 //std::cout << "linkLenMin: " << linkLenMin << "\n"; 00368 00369 T closestS = 0; 00370 //T err = Math<T>::MAX; 00371 //T err = std::numeric_limits<T>::max(); 00372 T err = 5E32; 00373 00374 //std::cout << "err: " << err << "\n"; 00375 00376 bool bFound = false; 00377 int count = 100; 00378 Vector3<T> helixOrg( a, 0, 0 ); 00379 do { 00380 s = ( prevMaxS - prevMinS )*0.5 + prevMinS; 00381 Vector3<T> point( a*cos(s), a*sin(s), b*s ); 00382 T length = ( point - helixOrg ).Length(); 00383 00384 //std::cout << "prevMaxS, s, prevMinS: " << prevMaxS << "\t" << s << "\t" << prevMinS << "\n"; 00385 //std::cout << "length: " << length << "\n"; 00386 00387 if ( length < linkLenMin ) prevMinS = s; 00388 else if ( length > linkLenMax ) prevMaxS = s; 00389 else bFound = true; 00390 00391 T newErr = fabs( length - m_Parameters.LinkLength ); 00392 if ( newErr < err ) { 00393 err = newErr; 00394 closestS = s; 00395 } 00396 00397 } while ( !bFound && --count > 0 ); 00398 00399 if ( !bFound ) s = closestS; 00400 00401 SetOfElasticRodNodes::iterator it = m_Nodes.begin(); 00402 while ( it != m_Nodes.end() ) { 00403 it->ID = id++; // assign id to the node 00404 it->Centerline[IdxCurr].SetMass( m_Parameters.MassOfPoint ); 00405 it->Centerline[IdxCurr].SetSize( m_Parameters.Radius ); 00406 it->Centerline[IdxCurr].SetPosition( position ); 00407 00408 // next position 00409 //t += it->CenterlineRestLength; 00410 00411 t += s; 00412 Vector3<T> next( a*cos(t), a*sin(t), b*t ); 00413 //next.Normalized(); 00414 //next *= it->CenterlineRestLength * ++count; 00415 00416 it->CenterlineRestLength = (next + offsetPos - position).Length(); 00417 00418 position = next + offsetPos; 00419 00420 //std::cout << "id: " << id-1 << "\t" << "it->CenterlineRestLength: " << it->CenterlineRestLength << "\n"; 00421 00422 it->Centerline[IdxPrev] = it->Centerline[IdxCurr]; // Initialize the previous centerline 00423 ++it; 00424 } 00425 } 00426 //*/ 00427 00428 00429 // Set orientation 00430 SetOfElasticRodNodes::iterator it = m_Nodes.begin(); 00431 for ( int i = 1; i < m_Parameters.NumOfNodes; ++i ) { 00432 // FIGURE IT OUT!!! 00433 // The orientation must have d3 points in the direction of 00434 // Centerline_next - Centerline_current 00435 00436 if ( shape == ShapeInitializationParameters::STRAIGHT_SHAPE ) { 00437 // SET A STRAIGHT LINE 00438 it->Orientation[IdxCurr].SetRIJK( 0, 1, 0, -1 ); // results in d3 is <-1,0,0> 00439 } 00440 else if ( shape == ShapeInitializationParameters::HELIX_SHAPE ) { 00441 // SET A HELIX 00442 Vector3<T> ptA = it->Centerline[IdxCurr].GetPosition(); 00443 ++it; 00444 Vector3<T> ptB = it->Centerline[IdxCurr].GetPosition(); 00445 --it; 00446 Matrix3x3<T> rotMat = CGMath<T>::CreateRotationMatrix3x3FromVectorAtoVectorB( ptA, ptB ); 00447 it->Orientation[IdxCurr].SetByRotationMatrix3x3( rotMat ); 00448 } 00449 it->Orientation[IdxCurr].Normalized(); // Initialize the previous orientation 00450 it->Orientation[IdxPrev] = it->Orientation[IdxCurr]; 00451 ++it; 00452 } 00453 00454 ComputeAndStoreCenterlineRestLengths(); 00455 ComputeAndStoreOrientationRestLengths(); 00456 00457 //* 00458 it = m_Nodes.begin(); 00459 // Compute the intrinsic strain rate of the orientations (except the last node) 00460 for ( int i = 1; i < m_Parameters.NumOfNodes-1; ++i ) { 00461 ComputeIntrinsicStrainRate( it ); 00462 ++it; 00463 } 00464 //*/ 00465 } 00466 00467 // Switch data accessing (previous becomes current and current becomes previous) 00468 template <typename T> 00469 void ModelElasticRod<T>::SwitchDataAccessing () 00470 { 00471 int tmp = IdxCurr; 00472 IdxCurr = IdxPrev; 00473 IdxPrev = tmp; 00474 } 00475 00476 // Compute and store the rest lengths of the orientation segments 00477 template <typename T> 00478 void ModelElasticRod<T>::ComputeAndStoreCenterlineRestLengths () 00479 { 00480 // CenterlineRestLength = (currCenterline - prevCenterline).Length() 00481 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00482 SetOfElasticRodNodes::iterator nextNode = currNode; 00483 ++nextNode; 00484 00485 while ( nextNode != m_Nodes.end() ) { 00486 currNode->CenterlineRestLength = ComputeLengthOfCenterlineSegment( 00487 currNode->Centerline[IdxCurr], nextNode->Centerline[IdxCurr] ); 00488 ++currNode; 00489 ++nextNode; 00490 } 00491 } 00492 00493 // Compute and store the rest lengths of the orientation segments 00494 template <typename T> 00495 void ModelElasticRod<T>::ComputeAndStoreOrientationRestLengths () 00496 { 00497 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00498 SetOfElasticRodNodes::iterator nextNode = currNode; 00499 ++nextNode; 00500 SetOfElasticRodNodes::iterator nextOfNextNode = nextNode; 00501 ++nextOfNextNode; 00502 00503 while ( nextOfNextNode != m_Nodes.end() ) { 00504 currNode->OrientationRestLength = ComputeLengthOfOrientationSegment( 00505 currNode->Centerline[IdxCurr], nextNode->Centerline[IdxCurr], nextOfNextNode->Centerline[IdxCurr] ); 00506 ++currNode; 00507 ++nextNode; 00508 ++nextOfNextNode; 00509 } 00510 } 00511 00512 // Reset 00513 template <typename T> 00514 void ModelElasticRod<T>::Reset () 00515 { 00516 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00517 while ( currNode != m_Nodes.end() ) { 00518 currNode->Reset(); 00519 ++currNode; 00520 } 00521 00522 Initialize( InitShapeParameters.StartShape ); 00523 00524 m_CD.Reset(); 00525 00526 #ifdef TAPs_ADD_KNOT_RECOGNITION 00527 m_KR.Reset(); 00528 #endif//TAPs_ADD_KNOT_RECOGNITION 00529 } 00530 00531 // Get the position of the start point 00532 template <typename T> 00533 Vector3<T> ModelElasticRod<T>::GetPosOfStartPt () 00534 { 00535 return m_Nodes.front().Centerline[IdxCurr].GetPosition(); 00536 } 00537 00538 // Get the position of the end point 00539 template <typename T> 00540 Vector3<T> ModelElasticRod<T>::GetPosOfEndPt () 00541 { 00542 return m_Nodes.back().Centerline[IdxCurr].GetPosition(); 00543 } 00544 00545 // Set the position of the start point 00546 template <typename T> 00547 void ModelElasticRod<T>::SetPosOfStartPt ( Vector3<T> const & pos, Quaternion<T> const & ori ) 00548 { 00549 m_Nodes.front().Centerline[IdxPrev].SetPosition( m_Nodes.front().Centerline[IdxCurr].GetPosition() ); 00550 m_Nodes.front().Centerline[IdxCurr].SetPosition( pos ); 00551 } 00552 00553 // Set the position of the end point 00554 template <typename T> 00555 void ModelElasticRod<T>::SetPosOfEndPt ( Vector3<T> const & pos, Quaternion<T> const & ori ) 00556 { 00557 m_Nodes.back().Centerline[IdxPrev].SetPosition( m_Nodes.back().Centerline[IdxCurr].GetPosition() ); 00558 m_Nodes.back().Centerline[IdxCurr].SetPosition( pos ); 00559 } 00560 00561 // Move the position of the start point 00562 template <typename T> 00563 void ModelElasticRod<T>::MovePosOfStartPt ( Vector3<T> const & pos, Quaternion<T> const & ori ) 00564 { 00565 m_Nodes.front().Centerline[IdxPrev].SetPosition( m_Nodes.front().Centerline[IdxCurr].GetPosition() ); 00566 m_Nodes.front().Centerline[IdxCurr].SetPosition( pos + m_Nodes.front().Centerline[IdxCurr].GetPosition() ); 00567 } 00568 00569 // Move the position of the end point 00570 template <typename T> 00571 void ModelElasticRod<T>::MovePosOfEndPt ( Vector3<T> const & pos, Quaternion<T> const & ori ) 00572 { 00573 m_Nodes.back().Centerline[IdxPrev].SetPosition( m_Nodes.back().Centerline[IdxCurr].GetPosition() ); 00574 m_Nodes.back().Centerline[IdxCurr].SetPosition( pos + m_Nodes.back().Centerline[IdxCurr].GetPosition() ); 00575 } 00576 00577 // Clear external forces 00578 template <typename T> 00579 void ModelElasticRod<T>::ClearExternalForces () 00580 { 00581 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00582 while ( currNode != m_Nodes.end() ) { 00583 (currNode->ExternalForce).Clear(); 00584 ++currNode; 00585 } 00586 } 00587 00588 // Clear external forces 00589 template <typename T> 00590 void ModelElasticRod<T>::ClearExternalForces_Reserved () 00591 { 00592 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00593 while ( currNode != m_Nodes.end() ) { 00594 (currNode->ExternalForce_Reserved).Clear(); 00595 ++currNode; 00596 } 00597 } 00598 00599 // Collision Detection and Response with an MBV (Multi-Bounding Volume) object 00600 template <typename T> 00601 bool ModelElasticRod<T>::CDRwith ( 00602 MultiBoundingVolume<T> * const pMBVObj, 00603 TransformationSupport<T> * const pTransform 00604 ) 00605 { 00606 return m_CD.CDRwith( pMBVObj, pTransform ); 00607 } 00608 00609 // Collision Detection and Response with an MBV (Multi-Bounding Volume) object 00610 template <typename T> 00611 bool ModelElasticRod<T>::CDRwith ( 00612 TAPs::OpenGL::HETriMeshOneModelMultiParts<T> * pObj, 00613 TransformationSupport<T> * const pTransform 00614 ) 00615 { 00616 return m_CD.CDRwith( pObj, pTransform ); 00617 } 00618 00619 // Clear internal forces 00620 template <typename T> 00621 void ModelElasticRod<T>::ClearInternalForces () 00622 { 00623 //std::cout << "ClearInternalForces\n"; 00624 00625 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00626 while ( currNode != m_Nodes.end() ) { 00627 currNode->Centerline[IdxCurr].SetForce( 0, 0, 0 ); 00628 //currNode->Centerline[IdxCurr].SetVelocity( 0, 0, 0 ); 00629 currNode->Torque.SetRIJK( 0, 0, 0, 0 ); 00630 ++currNode; 00631 } 00632 } 00633 00634 // Store internal forces 00635 template <typename T> 00636 void ModelElasticRod<T>::StoreInternalForces () 00637 { 00638 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00639 while ( currNode != m_Nodes.end() ) { 00640 currNode->OldInternalForce = currNode->Centerline[IdxCurr].GetForce(); 00641 currNode->OldInternalTorque = currNode->Torque; 00642 ++currNode; 00643 } 00644 } 00645 00646 // Restore internal forces 00647 template <typename T> 00648 void ModelElasticRod<T>::RestoreInternalForces () 00649 { 00650 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00651 while ( currNode != m_Nodes.end() ) { 00652 currNode->Centerline[IdxCurr].SetForce( currNode->OldInternalForce ); 00653 currNode->Torque = currNode->OldInternalTorque; 00654 ++currNode; 00655 } 00656 } 00657 00658 00659 // Advance Simulation by time step 00660 template <typename T> 00661 void ModelElasticRod<T>::AdvanceSimulation () 00662 { 00663 #if ER_TIMING_ADV_SIM != 0 00664 // TIMING 00665 static int times = -1; 00666 ++times; 00667 clock_t startTime, endTime; 00668 static clock_t compTime = 0; 00669 clock_t advSimStartTime, advSimEndTime; 00670 static clock_t advSimTime = 0; 00671 static bool isFirstRun = true; 00672 advSimStartTime = clock(); 00673 #endif 00674 00675 for ( unsigned int i = 0; i < m_Parameters.SimIterationTimes; ++i ) 00676 { 00677 #if ER_TIMING_ADV_SIM != 0 00678 startTime = clock(); // TIMING 00679 #endif 00680 00681 #ifdef TAPs_USE_CUDA 00682 if ( m_Parameters.EnableCUDA ) { 00683 //m_CUDA.AdvanceSimulation ( tCurrentTime, tNextTime, numOfSubSteps ); 00684 m_CUDA.AdvanceSimulation (); 00685 00686 // IMPORTANT!!! 00687 // Switch data accessing (previous becomes current and current becomes previous) 00688 SwitchDataAccessing(); 00689 00690 #if ER_TIMING_ADV_SIM != 0 00691 endTime = clock(); // TIMING 00692 if ( isFirstRun ) { 00693 isFirstRun = false; 00694 } 00695 else { 00696 compTime += endTime - startTime; // TIMING 00697 } 00698 #endif 00699 } 00700 else 00701 #endif//TAPs_USE_CUDA 00702 { 00703 // A simulation loop runs on CPU. 00704 AdvSimLoop(); 00705 00706 #if ER_TIMING_ADV_SIM != 0 00707 endTime = clock(); // TIMING 00708 if ( isFirstRun ) { 00709 isFirstRun = false; 00710 } 00711 else { 00712 compTime += endTime - startTime; // TIMING 00713 } 00714 #endif 00715 } 00716 00717 #if ER_TIMING_ADV_SIM != 0 00718 advSimEndTime = endTime = clock(); // TIMING 00719 if ( isFirstRun ) { 00720 isFirstRun = false; 00721 } 00722 else { 00723 advSimTime += advSimEndTime - advSimStartTime; // TIMING 00724 } 00725 00726 #ifdef TAPs_USE_CUDA 00727 if ( m_Parameters.EnableCUDA ) { 00728 if ( times == ER_TIMING_ADV_SIM_STOP ) { 00729 std::cout << "SIM (GPU) ACC TIME (for " << times << " times): " << 1000.0 * compTime / CLOCKS_PER_SEC << " ms.\n"; 00730 std::cout << "ADV SIM ACC TIME (for " << times << " times): " << 1000.0 * advSimTime / CLOCKS_PER_SEC << " ms.\n"; 00731 std::cout << std::endl; 00732 exit(-1); 00733 } 00734 } 00735 else 00736 #endif//TAPs_USE_CUDA 00737 { 00738 if ( times == ER_TIMING_ADV_SIM_STOP ) { 00739 std::cout << "SIM (CPU) ACC TIME (for " << times << " times): " << 1000.0 * compTime / CLOCKS_PER_SEC << " ms.\n"; 00740 std::cout << "ADV SIM ACC TIME (for " << times << " times): " << 1000.0 * advSimTime / CLOCKS_PER_SEC << " ms.\n"; 00741 std::cout << std::endl; 00742 exit(-1); 00743 } 00744 } 00745 #endif 00746 00747 } // END: for ( unsigned int i = 0; i < m_Parameters.SimIterationTimes; ++i ) {} 00748 } 00749 00750 // Advance simulation loop (on CPU) 00751 template <typename T> 00752 void ModelElasticRod<T>::AdvSimLoop () 00753 { 00754 00755 00756 #if ER_TIMING_ADV_SIM != 0 00757 // TIMING 00758 static bool isFirstRun = true; 00759 static int times = 0; 00760 static clock_t compTime = 0; 00761 clock_t startTime, endTime; 00762 #endif 00763 00764 #if ER_TIMING_ADV_SIM != 0 00765 startTime = clock(); 00766 #endif 00767 00768 #if ER_TIMING_ADV_SIM_DETAILS != 0 00769 // TIMING 00770 static clock_t T_clear_forces = 0; // time for clear forces (both centerlines and orientations) 00771 static clock_t T_clear_forces_MAX = 0; // MAX time for clear forces (both centerlines and orientations) 00772 static clock_t T_clear_forces_MIN = 777; // MIN time for clear forces (both centerlines and orientations) 00773 clock_t Start_T_clear_forces = 0; // start time for collision detection update BVH 00774 clock_t End_T_clear_forces = 0; // end time for collision detection update BVH 00775 00776 // Timing for the inner sim loop 00777 static clock_t T_inner_sim_loop = 0; 00778 static clock_t T_inner_sim_loop_MAX = 0; 00779 static clock_t T_inner_sim_loop_MIN = 777; 00780 clock_t Start_T_inner_sim_loop = 0; 00781 clock_t End_T_inner_sim_loop = 0; 00782 00783 static clock_t T_CD_update = 0; // time for collision detection update BVH 00784 static clock_t T_CD_self = 0; // time for collision detection self intersections 00785 static clock_t T_FC_centerline = 0; // time for force computation of centerlines 00786 static clock_t T_FC_orientation = 0; // time for force computation of orientations 00787 static clock_t T_Int_centerline = 0; // time for integration of centerlines 00788 static clock_t T_Int_orientations = 0; // time for integration of orientations 00789 static clock_t T_CD_update_MAX = 0; // MAX time for collision detection update BVH 00790 static clock_t T_CD_self_MAX = 0; // MAX time for collision detection self intersections 00791 static clock_t T_FC_centerline_MAX = 0; // MAX time for force computation of centerlines 00792 static clock_t T_FC_orientation_MAX = 0; // MAX time for force computation of orientations 00793 static clock_t T_Int_centerline_MAX = 0; // MAX time for integration of centerlines 00794 static clock_t T_Int_orientations_MAX = 0; // MAX time for integration of orientations 00795 static clock_t T_CD_update_MIN = 777; // MIN time for collision detection update BVH 00796 static clock_t T_CD_self_MIN = 777; // MIN time for collision detection self intersections 00797 static clock_t T_FC_centerline_MIN = 777; // MIN time for force computation of centerlines 00798 static clock_t T_FC_orientation_MIN = 777; // MIN time for force computation of orientations 00799 static clock_t T_Int_centerline_MIN = 777; // MIN time for integration of centerlines 00800 static clock_t T_Int_orientations_MIN = 777; // MIN time for integration of orientations 00801 clock_t Start_T_CD_update = 0; // start time for collision detection update BVH 00802 clock_t Start_T_CD_self = 0; // start time for collision detection self intersections 00803 clock_t Start_T_FC_centerline = 0; // start time for force computation of centerlines 00804 clock_t Start_T_FC_orientation = 0; // start time for force computation of orientations 00805 clock_t Start_T_Int_centerline = 0; // start time for integration of centerlines 00806 clock_t Start_T_Int_orientations = 0; // start time for integration of orientations 00807 clock_t End_T_CD_update = 0; // end time for collision detection update BVH 00808 clock_t End_T_CD_self = 0; // end time for collision detection self intersections 00809 clock_t End_T_FC_centerline = 0; // end time for force computation of centerlines 00810 clock_t End_T_FC_orientation = 0; // end time for force computation of orientations 00811 clock_t End_T_Int_centerline = 0; // end time for integration of centerlines 00812 clock_t End_T_Int_orientations = 0; // end time for integration of orientations 00813 #endif 00814 00815 #if ER_TIMING_ADV_SIM_DETAILS != 0 00816 Start_T_clear_forces = clock(); 00817 #endif 00818 00819 ClearInternalForces(); 00820 00821 #if ER_TIMING_ADV_SIM_DETAILS != 0 00822 End_T_clear_forces = clock(); 00823 if ( !isFirstRun ) { 00824 clock_t timediff = End_T_clear_forces - Start_T_clear_forces; 00825 T_clear_forces += timediff; 00826 if ( T_clear_forces_MAX < timediff ) T_clear_forces_MAX = timediff; 00827 if ( T_clear_forces_MIN > timediff ) T_clear_forces_MIN = timediff; 00828 if ( times >= ER_TIMING_ADV_SIM_STOP-1 ) { 00829 std::cout << "Time to clear forces (both centerlines and orientations) (for " << times << " times): " << 1000.0 * T_clear_forces / CLOCKS_PER_SEC 00830 << " ms with (MIN & MAX: " << T_clear_forces_MIN << " & " << T_clear_forces_MAX << ").\n"; 00831 } 00832 } 00833 #endif 00834 00835 #ifdef TAPs_SIM_WITH_POSITION_BASED_DYNAMICS 00836 #else //TAPs_SIM_WITH_POSITION_BASED_DYNAMICS 00837 // Update the tree and check for self intersection (resolving collision by setting internal forces) 00838 UpdateBVHTree(); 00839 CDRforSelfIntersections(); 00840 #endif//TAPs_SIM_WITH_POSITION_BASED_DYNAMICS 00841 00842 #if ER_TIMING_ADV_SIM_DETAILS != 0 00843 Start_T_inner_sim_loop = clock(); 00844 #endif 00845 00846 #ifdef TAPs_ADD_KNOT_RECOGNITION 00847 //m_KR.ComputeStickPairForce(); 00848 #endif//TAPs_ADD_KNOT_RECOGNITION 00849 00850 // Simulation Loop 00851 int count = 0; 00852 SetOfElasticRodNodes::iterator currNode = m_Nodes.begin(); 00853 00854 while ( currNode != m_Nodes.end() ) { 00855 00856 // Computing forces for centerline (except the last node) 00857 if ( ++count < m_Parameters.NumOfNodes ) { 00858 00859 // Compute the constraint force for both centerlines and the quaternion 00860 ComputeConstraintForceOfCenterlineAndOrientation( currNode ); 00861 00862 ComputeStretchForceOfCenterline( currNode ); 00863 00864 ComputeBendTorqueOfQuaternion( currNode ); 00865 00866 #ifdef USE_CORDE_SIM 00867 ComputeTranslationalDissipationForceOfCenterline( currNode ); 00868 ComputeRotationalDissipationTorqueOfQuaternion( currNode ); 00869 ComputeKineticForceOfCenterline( currNode ); 00870 ComputeKineticTorqueOfQuaternion( currNode ); 00871 #endif//USE_CORDE_SIM 00872 } 00873 00874 // For each centerline 00875 ComputeGravitationalForceOfCenterline( currNode ); 00876 //ComputeGravitationalVelocityOfCenterline( h, currNode ); 00877 ComputeDampingVelocityOfCenterline( currNode ); 00878 00879 #ifdef TAPs_ADVANCED_SIMULATION 00880 if ( !currNode->SimFlags.CheckSimulationConstraints( Enum::AddOn::FIXED ) ) 00881 #endif//TAPs_ADVANCED_SIMULATION 00882 { 00883 //----------------------------------------------------------- 00884 // SEMI-IMPLICIT EULER SCHEME FOR CENTERLINE 00885 //----------------------------------------------------------- 00886 // Since force will be clear before starting the force computation for the next time step, 00887 // maintain the force information can be neglected. 00888 00889 // The statement below is replaced by the one without currNode->Centerline[IdxCurr].GetVelocity() 00890 //currNode->Centerline[IdxNext].SetVelocity( h/currNode->Centerline[IdxCurr].GetMass() 00891 // * (currNode->Centerline[IdxCurr].GetForce() + currNode->ExternalForce + currNode->ExternalForce_Reserved) ); 00892 00893 00894 #ifdef TAPs_ADVANCED_SELF_COLLISION_DETECTION 00895 //m_CD.SelfCDExtraDataTrackStatus( currNode->ID ); 00896 #endif//TAPs_ADVANCED_SELF_COLLISION_DETECTION 00897 00898 // Next velocity 00899 currNode->Centerline[IdxNext].SetVelocity( currNode->Centerline[IdxCurr].GetVelocity() 00900 + m_Parameters.TimeStep/currNode->Centerline[IdxCurr].GetMass() 00901 * ( currNode->Centerline[IdxCurr].GetForce() 00902 + currNode->ExternalForce // the ExternalForce is used for CD collision force 00903 + currNode->ExternalForce_Reserved // the ExternalForce_Reserved is used in the classes inherited from this class 00904 + currNode->ExternalForce_Constrained // the ExternalForce_Constrained is used by class TAPsAdvSimConstraints.hpp 00905 + currNode->ExternalForce_ForAdvSimCtrl ) 00906 00907 ); 00908 // Next position 00909 currNode->Centerline[IdxNext].SetPosition( 00910 currNode->Centerline[IdxCurr].GetPosition() 00911 + m_Parameters.TimeStep*currNode->Centerline[IdxNext].GetVelocity() 00912 ); 00913 00914 //----------------------------------------------------------- 00915 // For each orientation (except the last node) 00916 if ( count < m_Parameters.NumOfNodes-1 ) { 00917 00918 //----------------------------------------------------------- 00919 // SEMI-IMPLICIT EULER SCHEME FOR ORIENTATION 00920 //----------------------------------------------------------- 00921 // Compute the components of the inverse of the inertia tensor matrix 00922 T A = m_Parameters.MaterialDensity * Math<T>::PI * m_Parameters.Radius*m_Parameters.Radius; 00923 T B = currNode->OrientationRestLength * A; 00924 Jinv[0,0] = Jinv[1,1] = 4 / B; 00925 Jinv[2,2] = 2 / A; 00926 // Compute the angular velocity from the 4d torque 00927 // 1/2 * Q_j^T * torque_in_4Dim 00928 // (Q_j^T * torque_in_4Dim) equals "the multiplication of conjugation_of_q_j with torque_in_4Dim" 00929 Quaternion<T> torque_transformed( T(0.5) * currNode->Orientation[IdxCurr].GetConjugate() * currNode->Torque ); 00930 // Angular velocity := 1/2 * Jinv * torque_transformed_into_3Dim 00931 Quaternion<T> angularVelocity( 00932 0, // deliberately set to zero 00933 0.5*Jinv[0,0]*torque_transformed.GetI(), 00934 0.5*Jinv[1,1]*torque_transformed.GetJ(), 00935 0.5*Jinv[2,2]*torque_transformed.GetK() 00936 ); 00937 00938 // Compute the velocity of the quaternion 00939 Quaternion<T> q_velocity( T(0.5) * currNode->Orientation[IdxCurr] * angularVelocity ); 00940 00941 // Set the next quaternion 00942 currNode->Orientation[IdxNext] = currNode->Orientation[IdxCurr] + q_velocity*m_Parameters.TimeStep; 00943 //----------------------------------------------------------- 00944 00945 //----------------------------------------------------------- 00946 // For each orientation 00947 // Renormalize the quaternion, by the coordinate projection method 00948 currNode->Orientation[IdxNext].Normalized(); 00949 //----------------------------------------------------------- 00950 } 00951 00952 #ifdef TAPs_ADVANCED_SELF_COLLISION_DETECTION 00953 m_CD.CheckAndRestoreWithSelfCDExtraData( currNode->ID ); 00954 #endif//TAPs_ADVANCED_SELF_COLLISION_DETECTION 00955 00956 // Enforce Suture's Position 00957 if ( currNode->UseEnforcedPosition ) { 00958 currNode->Centerline[IdxNext].SetPosition( currNode->EnforcedPosition ); 00959 00960 // Average between the new calculated position and the enforced position 00961 //currNode->Centerline[IdxNext].SetPosition( ( currNode->EnforcedPosition + currNode->Centerline[IdxNext].GetPosition() ) * T(0.5) ); 00962 //currNode->Centerline[IdxNext].SetPosition( ( currNode->EnforcedPosition*T(7) + currNode->Centerline[IdxNext].GetPosition()*T(3) ) * T(0.1) ); 00963 00964 } 00965 // Enforce Suture's Orientation 00966 if ( currNode->UseEnforcedOrientation ) { 00967 currNode->Orientation[IdxNext] = currNode->EnforcedOrientation; 00968 } 00969 00970 } 00971 ++currNode; 00972 } 00973 00974 #if ER_TIMING_ADV_SIM_DETAILS != 0 00975 End_T_inner_sim_loop = clock(); 00976 if ( !isFirstRun ) { 00977 clock_t timediff = End_T_inner_sim_loop - Start_T_inner_sim_loop; 00978 T_inner_sim_loop += timediff; 00979 if ( T_inner_sim_loop_MAX < timediff ) T_inner_sim_loop_MAX = timediff; 00980 if ( T_inner_sim_loop_MIN > timediff ) T_inner_sim_loop_MIN = timediff; 00981 if ( times >= ER_TIMING_ADV_SIM_STOP-1 ) { 00982 std::cout << "Time of inner sim loop (for " << times << " times): " << 1000.0 * T_inner_sim_loop / CLOCKS_PER_SEC 00983 << " ms with (MIN & MAX: " << T_inner_sim_loop_MIN << " & " << T_inner_sim_loop_MAX << ").\n"; 00984 } 00985 } 00986 #endif 00987 00988 #ifdef TAPs_SIM_WITH_POSITION_BASED_DYNAMICS 00989 // Update the tree and check for self intersection (resolving collision by geometric setting) 00990 UpdateBVHTree_PBD(); 00991 CDRforSelfIntersections_PBD(); 00992 UpdateVelocities_PBD( m_Parameters.TimeStep ); 00993 #endif//TAPs_SIM_WITH_POSITION_BASED_DYNAMICS 00994 00995 00996 // Update the extra self CD data 00997 #ifdef TAPs_ADVANCED_SELF_COLLISION_DETECTION 00998 //m_CD.PreventMissedCDWithSelfCDExtraData(); 00999 m_CD.UpdateSelfCDExtraData(); 01000 #endif//TAPs_ADVANCED_SELF_COLLISION_DETECTION 01001 01002 01003 #ifdef TAPs_ADD_KNOT_RECOGNITION 01004 #ifdef TAPs_ADD_ANIMATED_KNOTS 01005 m_KR.ProcessKnotAnimation(); 01006 #endif//TAPs_ADD_ANIMATED_KNOTS 01007 m_KR.ConstrainKnots(); 01008 #endif//TAPs_ADD_KNOT_RECOGNITION 01009 01010 // IMPORTANT!!! 01011 // Switch data accessing (previous becomes current and current becomes previous) 01012 SwitchDataAccessing(); 01013 01014 #if ER_TIMING_ADV_SIM != 0 01015 endTime = clock(); // TIMING 01016 if ( !isFirstRun ) { 01017 compTime += endTime - startTime; // TIMING 01018 ++times; 01019 } 01020 #endif 01021 01022 #if ER_TIMING_ADV_SIM != 0 01023 if ( isFirstRun ) isFirstRun = false; 01024 std::cout << "SIM (CPU) INNER AdvSim TIME (for " << times << " times): " << 1000.0 * compTime / CLOCKS_PER_SEC << " ms.\n"; 01025 #endif 01026 } 01027 01028 // Compute the length of a centerline segment 01029 template <typename T> 01030 T ModelElasticRod<T>::ComputeLengthOfCenterlineSegment ( 01031 PointMass<T> const & c1, 01032 PointMass<T> const & c2 ) 01033 { 01034 return (c2.GetPosition()-c1.GetPosition()).Length(); 01035 } 01036 01037 // Compute the length of an orientation segment 01038 template <typename T> 01039 T ModelElasticRod<T>::ComputeLengthOfOrientationSegment ( 01040 PointMass<T> const & c1, 01041 PointMass<T> const & c2, 01042 PointMass<T> const & c3 ) 01043 { 01044 // The formula from the CORDE model 01045 //return 0.5*((c3.GetPosition()-c2.GetPosition()).Length()+(c2.GetPosition()-c1.GetPosition()).Length()); 01046 // But the formula should return the length of vector ( (c3+c2)*0.5 - (c2+c1)*0.5 ) 01047 // | | 01048 // V V 01049 // midPtOf[c3,c2] midPtOf[c2,c1] 01050 // Which is simplified to 01051 return 0.5 * ( c3.GetPosition()-c1.GetPosition() ).Length(); 01052 } 01053 01054 // Compute the stretch force of a centerline 01055 template <typename T> 01056 void ModelElasticRod<T>::ComputeStretchForceOfCenterline ( 01057 typename SetOfElasticRodNodes::iterator & iterNode ) 01058 { 01059 // Current node 01060 ElasticRodNode<T> & currNode = *iterNode; 01061 // Next Node 01062 ElasticRodNode<T> & nextNode = *(++iterNode); 01063 --iterNode; // return to the current position 01064 01065 // Compute the stretch force 01066 // F_s = K_s * ( curr_len/rest_len - 1 ) * (nextPtMass-currPtMass)/curr_len 01067 Vector3<T> p2_p1 = nextNode.Centerline[IdxCurr].GetPosition() - currNode.Centerline[IdxCurr].GetPosition(); 01068 T currLength = p2_p1.Length(); 01069 01070 T ratio = currLength/currNode.CenterlineRestLength - 1; 01071 T stretchMagnitude = ratio * m_Parameters.Ps * 10; 01072 01073 //----------------------------------------- 01074 #ifdef TAPs_USE_NONLINEAR_FORCES 01075 #else //TAPs_USE_NONLINEAR_FORCES 01076 #endif//TAPs_USE_NONLINEAR_FORCES 01077 //----------------------------------------- 01078 01079 Vector3<T> stretchForce = stretchMagnitude * p2_p1/currLength; 01080 01081 // Add the stretch force to the nodes' total force 01082 currNode.Centerline[IdxCurr].SetForce( currNode.Centerline[IdxCurr].GetForce() + stretchForce ); 01083 nextNode.Centerline[IdxCurr].SetForce( nextNode.Centerline[IdxCurr].GetForce() - stretchForce ); 01084 } 01085 01086 01087 #ifdef USE_CORDE_SIM 01088 // Compute the translational dissipation force of a centerline 01089 template <typename T> 01090 void ModelElasticRod<T>::ComputeTranslationalDissipationForceOfCenterline ( 01091 typename SetOfElasticRodNodes::iterator & iterNode ) 01092 { 01093 // Current node 01094 ElasticRodNode<T> & currNode = *iterNode; 01095 Vector3<T> const & pos0 = currNode.Centerline[IdxCurr].GetPosition(); 01096 Vector3<T> const & prevpos0 = currNode.Centerline[IdxPrev].GetPosition(); 01097 Vector3<T> const & vel0 = ( pos0 - prevpos0 ) * m_Parameters.TimeStep; 01098 //Vector3<T> const & vel0 = currNode.Centerline[IdxCurr].GetVelocity(); 01099 // Next Node 01100 ElasticRodNode<T> & nextNode = *(++iterNode); 01101 Vector3<T> const & pos1 = nextNode.Centerline[IdxCurr].GetPosition(); 01102 Vector3<T> const & prevpos1 = nextNode.Centerline[IdxPrev].GetPosition(); 01103 Vector3<T> const & vel1 = ( pos1 - prevpos1 ) * m_Parameters.TimeStep; 01104 //Vector3<T> const & vel1 = nextNode.Centerline[IdxCurr].GetVelocity(); 01105 --iterNode; // return to the current position 01106 01107 01108 // Compute the translational dissipation force 01109 Vector3<T> posRel( pos1-pos0 ); 01110 Vector3<T> velRel( vel1-vel0 ); 01111 Vector3<T> Vrel = posRel * ( velRel * posRel ); 01112 01113 T x01 = pos0[0] - pos1[0]; 01114 T y01 = pos0[1] - pos1[1]; 01115 T z01 = pos0[2] - pos1[2]; 01116 T x10 = -x01; 01117 T y10 = -y01; 01118 T z10 = -z01; 01119 01120 Vector3<T> transDissipationForce_0( 01121 Vrel[2]*x01*z10 + Vrel[1]*x01*y10 + Vrel[0]*x01*x10, 01122 Vrel[2]*y01*z10 + Vrel[1]*y01*y10 + Vrel[0]*y01*x10, 01123 Vrel[2]*z01*z10 + Vrel[1]*z01*y10 + Vrel[0]*z01*x10 01124 ); 01125 T s = pow( currNode.CenterlineRestLength, 5 ) * 2; 01126 transDissipationForce_0 *= m_Parameters.Dt / s; 01127 01128 //Since transDissipationForce_1 = -transDissipationForce_0; 01129 //Vector3<T> transDissipationForce_1( 01130 // Vrel[2]*x10*z10 + Vrel[1]*x10*y10 + Vrel[0]*x10*x10, 01131 // Vrel[2]*y10*z10 + Vrel[1]*y10*y10 + Vrel[0]*y10*x10, 01132 // Vrel[2]*z10*z10 + Vrel[1]*z10*y10 + Vrel[0]*z10*x10 01133 //); 01134 //transDissipationForce_1 *= m_Parameters.Dt / s; 01135 01136 // Add the force to the nodes' total force 01137 currNode.Centerline[IdxCurr].SetForce( currNode.Centerline[IdxCurr].GetForce() - transDissipationForce_0 ); 01138 nextNode.Centerline[IdxCurr].SetForce( nextNode.Centerline[IdxCurr].GetForce() + transDissipationForce_0 ); 01139 } 01140 01141 // Compute the kinetic force of a centerline 01142 template <typename T> 01143 void ModelElasticRod<T>::ComputeKineticForceOfCenterline ( 01144 typename SetOfElasticRodNodes::iterator & iterNode ) 01145 { 01146 // Current node 01147 ElasticRodNode<T> & currNode = *iterNode; 01148 Vector3<T> const & pos0 = currNode.Centerline[IdxCurr].GetPosition(); 01149 Vector3<T> const & prevpos0 = currNode.Centerline[IdxPrev].GetPosition(); 01150 Vector3<T> const & vel0 = ( pos0 - prevpos0 ) * m_Parameters.TimeStep; 01151 // Next Node 01152 ElasticRodNode<T> & nextNode = *(++iterNode); 01153 Vector3<T> const & pos1 = nextNode.Centerline[IdxCurr].GetPosition(); 01154 Vector3<T> const & prevpos1 = nextNode.Centerline[IdxPrev].GetPosition(); 01155 Vector3<T> const & vel1 = ( pos1 - prevpos1 ) * m_Parameters.TimeStep; 01156 --iterNode; // return to the current position 01157 01158 // Compute the kinetic force 01159 Vector3<T> V10( vel1 + vel0 ); 01160 T s = currNode.CenterlineRestLength * 0.25 * Math<T>::PI * m_Parameters.Radius*m_Parameters.Radius * m_Parameters.MaterialDensity; 01161 Vector3<T> Fk = s * m_Parameters.Kt * V10; 01162 01163 // Add the force to the nodes' total force 01164 currNode.Centerline[IdxCurr].SetForce( currNode.Centerline[IdxCurr].GetForce() - Fk ); 01165 nextNode.Centerline[IdxCurr].SetForce( nextNode.Centerline[IdxCurr].GetForce() - Fk ); 01166 } 01167 #endif//USE_CORDE_SIM 01168 01169 01170 // Compute the damping force of a centerline 01171 template <typename T> 01172 void ModelElasticRod<T>::ComputeDampingVelocityOfCenterline ( 01173 typename SetOfElasticRodNodes::iterator & iterNode ) 01174 { 01175 // Current node 01176 Vector3<T> const & vel = iterNode->Centerline[IdxCurr].GetVelocity(); 01177 01178 // Compute the damping velocity 01179 Vector3<T> velocityAfterDamping = m_Parameters.Kvdamping * vel; 01180 01181 // Add the damping velocity to the nodes' velocity 01182 iterNode->Centerline[IdxCurr].SetVelocity( velocityAfterDamping ); 01183 } 01184 01185 // Compute the gravitational force of a centerline 01186 template <typename T> 01187 void ModelElasticRod<T>::ComputeGravitationalForceOfCenterline ( 01188 typename SetOfElasticRodNodes::iterator & iterNode ) 01189 { 01190 // Skip if reaching the end of falling 01191 #ifdef TAPs_ADD_RESTING_LEVEL_Y 01192 if ( iterNode->Centerline[IdxCurr].GetPosition()[1] > m_Parameters.Radius + m_Parameters.RestingLevel ) { 01193 iterNode->Centerline[IdxCurr].GetForce()[1] += m_Parameters.Kgravity * iterNode->Centerline[IdxCurr].GetMass(); 01194 } 01195 #ifdef TAPs_SPECIFIC_FOR_SUTUREAPP_02 01196 else if ( iterNode->Centerline[IdxCurr].GetPosition()[1] < -m_Parameters.Radius + m_Parameters.RestingLevel ) { 01197 iterNode->Centerline[IdxCurr].GetForce()[1] -= m_Parameters.Kgravity*10 * iterNode->Centerline[IdxCurr].GetMass(); 01198 } 01199 #endif//TAPs_SPECIFIC_FOR_SUTUREAPP_02 01200 #endif//TAPs_ADD_RESTING_LEVEL_Y 01201 // Compute and add the gravitational force 01202 iterNode->Centerline[IdxCurr].GetForce()[1] += m_Parameters.Kgravity * iterNode->Centerline[IdxCurr].GetMass(); 01203 } 01204 01205 // Compute the intrinsic strain rate 01206 template <typename T> 01207 void ModelElasticRod<T>::ComputeIntrinsicStrainRate ( 01208 typename SetOfElasticRodNodes::iterator & iterNode ) 01209 { 01210 if ( iterNode == m_Nodes.end() ) return; 01211 01212 // Current node {j} 01213 ElasticRodNode<T> & currNode = *iterNode; 01214 Quaternion<T> & q = currNode.Orientation[IdxCurr]; 01215 // Next Node {j+1} 01216 ElasticRodNode<T> & nextNode = *(++iterNode); 01217 01218 if ( iterNode == m_Nodes.end() ) return; 01219 01220 Quaternion<T> & qn = nextNode.Orientation[IdxCurr]; 01221 --iterNode; // return to the current position 01222 01223 // Compute the bend force 01224 Quaternion<T> qa( qn + q ); // q_{j+1} + q_{j} 01225 Quaternion<T> qs( qn - q ); // q_{j+1} - q_{j} 01226 01227 // B_k(q_{j+1}+q{j}) 01228 T invRestLen = T(1.0) / currNode.OrientationRestLength; 01229 currNode.IntrinsicStrainRate[0] = B_1(qa).InnerProduct( qs ) * invRestLen; 01230 currNode.IntrinsicStrainRate[1] = B_2(qa).InnerProduct( qs ) * invRestLen; 01231 currNode.IntrinsicStrainRate[2] = B_3(qa).InnerProduct( qs ) * invRestLen; 01232 01233 // Differentiation of ( B_k(q_{j+1}+q{j}) inner_product_with (q_{j+1}-q{j}) ) 01234 // by q_{j} 01235 currNode.IntrinsicStrainQ[0].SetRIJK( -qn.GetI(), qn.GetR(), qn.GetK(), -qn.GetJ() ); 01236 currNode.IntrinsicStrainQ[1].SetRIJK( -qn.GetJ(), -qn.GetK(), qn.GetR(), qn.GetI() ); 01237 currNode.IntrinsicStrainQ[2].SetRIJK( -qn.GetK(), qn.GetJ(), -qn.GetI(), qn.GetR() ); 01238 // Differentiation of ( B_k(q_{j+1}+q{j}) inner_product_with (q_{j+1}-q{j}) ) 01239 // by q_{j+1} 01240 currNode.IntrinsicStrainQn[0].SetRIJK( q.GetI(), -q.GetR(), -q.GetK(), q.GetJ() ); 01241 currNode.IntrinsicStrainQn[1].SetRIJK( q.GetJ(), q.GetK(), -q.GetR(), -q.GetI() ); 01242 currNode.IntrinsicStrainQn[2].SetRIJK( q.GetK(), -q.GetJ(), q.GetI(), -q.GetR() ); 01243 } 01244 01245 // Compute the bend force (torque) of an orientation 01246 template <typename T> 01247 void ModelElasticRod<T>::ComputeBendTorqueOfQuaternion ( 01248 typename SetOfElasticRodNodes::iterator & iterNode ) 01249 { 01250 // Current node {j} 01251 ElasticRodNode<T> & currNode = *iterNode; 01252 Quaternion<T> & q = currNode.Orientation[IdxCurr]; 01253 // Next Node {j+1} 01254 ElasticRodNode<T> & nextNode = *(++iterNode); 01255 Quaternion<T> & qn = nextNode.Orientation[IdxCurr]; 01256 --iterNode; // return to the current position 01257 01258 // Compute the bend force 01259 Quaternion<T> qa( qn + q ); // q_{j+1} + q_{j} 01260 Quaternion<T> qs( qn - q ); // q_{j+1} - q_{j} 01261 01262 // B_k(q_{j+1}+q{j}) 01263 Quaternion<T> B1qa( B_1(qa) ); 01264 Quaternion<T> B2qa( B_2(qa) ); 01265 Quaternion<T> B3qa( B_3(qa) ); 01266 01267 // K_k ( B_k(q_{j+1}+q{j})/rest_length inner_product_with (q_{j+1}-q{j}) ) 01268 T invRestLen = T(1.0) / currNode.OrientationRestLength; 01269 T KB1 = m_Parameters.Pb[0] * ( B1qa.InnerProduct( qs )*invRestLen - currNode.IntrinsicStrainRate[0]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate ); 01270 T KB2 = m_Parameters.Pb[1] * ( B2qa.InnerProduct( qs )*invRestLen - currNode.IntrinsicStrainRate[1]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate ); 01271 T KB3 = m_Parameters.Pb[2] * ( B3qa.InnerProduct( qs )*invRestLen - currNode.IntrinsicStrainRate[2]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate ); 01272 01273 // Differentiation of ( B_k(q_{j+1}+q{j}) inner_product_with (q_{j+1}-q{j}) ) 01274 // by q_{j} 01275 Quaternion<T> dB1_q( -qn.GetI(), qn.GetR(), qn.GetK(), -qn.GetJ() ); 01276 Quaternion<T> dB2_q( -qn.GetJ(), -qn.GetK(), qn.GetR(), qn.GetI() ); 01277 Quaternion<T> dB3_q( -qn.GetK(), qn.GetJ(), -qn.GetI(), qn.GetR() ); 01278 // Differentiation of ( B_k(q_{j+1}+q{j}) inner_product_with (q_{j+1}-q{j}) ) 01279 // by q_{j+1} 01280 Quaternion<T> dB1_qn( q.GetI(), -q.GetR(), -q.GetK(), q.GetJ() ); 01281 Quaternion<T> dB2_qn( q.GetJ(), q.GetK(), -q.GetR(), -q.GetI() ); 01282 Quaternion<T> dB3_qn( q.GetK(), -q.GetJ(), q.GetI(), -q.GetR() ); 01283 01284 // Add the bend torque to the total torque 01285 currNode.Torque += KB1*(dB1_q - currNode.IntrinsicStrainQ[0]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate) 01286 + KB2*(dB2_q - currNode.IntrinsicStrainQ[1]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate) 01287 + KB3*(dB3_q - currNode.IntrinsicStrainQ[2]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate); 01288 nextNode.Torque += KB1*(dB1_qn - currNode.IntrinsicStrainQn[0]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate) 01289 + KB2*(dB2_qn - currNode.IntrinsicStrainQn[1]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate) 01290 + KB3*(dB3_qn - currNode.IntrinsicStrainQn[2]*m_Parameters.Kconstraint_ScaleIntrinsicStrainRate); 01291 } 01292 01293 01294 #ifdef USE_CORDE_SIM 01295 // Compute the rotational dissipation torque of an orientation 01296 template <typename T> 01297 void ModelElasticRod<T>::ComputeRotationalDissipationTorqueOfQuaternion ( 01298 typename SetOfElasticRodNodes::iterator & iterNode ) 01299 { 01300 T inv_timestep = T(1) / m_Parameters.TimeStep; 01301 // Current node {j} 01302 ElasticRodNode<T> & currNode = *iterNode; 01303 Quaternion<T> & q = currNode.Orientation[IdxCurr]; 01304 Quaternion<T> & q_prev = currNode.Orientation[IdxPrev]; 01305 Quaternion<T> q_v = ( q_prev - q ) * inv_timestep; 01306 // Next Node {j+1} 01307 ElasticRodNode<T> & nextNode = *(++iterNode); 01308 Quaternion<T> & qn = nextNode.Orientation[IdxCurr]; 01309 Quaternion<T> & qn_prev = nextNode.Orientation[IdxPrev]; 01310 Quaternion<T> qn_v = ( qn_prev - qn ) * inv_timestep; 01311 --iterNode; // return to the current position 01312 01313 // 01314 // Compute the rotational torque 01315 // 01316 T q_1 = B0_1(qn).InnerProduct(qn_v) - B0_1(q).InnerProduct(q_v); 01317 T q_2 = B0_2(qn).InnerProduct(qn_v) - B0_2(q).InnerProduct(q_v); 01318 T q_3 = B0_3(qn).InnerProduct(qn_v) - B0_3(q).InnerProduct(q_v); 01319 T Q = m_Parameters.Dr[0]*q_1 + m_Parameters.Dr[1]*q_2 + m_Parameters.Dr[2]*q_3; 01320 // 01321 T Ar = q.GetK() + q.GetJ() + q.GetI(); 01322 T Ai = -q.GetR() - q.GetK() + q.GetJ(); 01323 T Aj = -q.GetR() + q.GetK() - q.GetI(); 01324 T Ak = -q.GetR() - q.GetJ() + q.GetI(); 01325 // 01326 T Br = -qn.GetK() - qn.GetJ() - qn.GetI(); 01327 T Bi = qn.GetR() + qn.GetK() - qn.GetJ(); 01328 T Bj = qn.GetR() - qn.GetK() + qn.GetI(); 01329 T Bk = qn.GetR() + qn.GetJ() - qn.GetI(); 01330 // 01331 T s = 4 / m_Parameters.LinkLength; 01332 Q *= s; 01333 Quaternion<T> Tr_0( Q * Quaternion<T>( Ar, Ai, Aj, Ak ) ); 01334 Quaternion<T> Tr_1( Q * Quaternion<T>( Br, Bi, Bj, Bk ) ); 01335 // 01336 currNode.Torque -= Tr_0; 01337 nextNode.Torque -= Tr_1; 01338 } 01339 01340 // Compute the kinetic torque of an orientation 01341 template <typename T> 01342 void ModelElasticRod<T>::ComputeKineticTorqueOfQuaternion ( 01343 typename SetOfElasticRodNodes::iterator & iterNode ) 01344 { 01345 T inv_timestep = T(1) / m_Parameters.TimeStep; 01346 // Current node {j} 01347 ElasticRodNode<T> & currNode = *iterNode; 01348 Quaternion<T> & q = currNode.Orientation[IdxCurr]; 01349 Quaternion<T> & q_prev = currNode.Orientation[IdxPrev]; 01350 Quaternion<T> q_v = ( q_prev - q ) * inv_timestep; 01351 // Next Node {j+1} 01352 ElasticRodNode<T> & nextNode = *(++iterNode); 01353 Quaternion<T> & qn = nextNode.Orientation[IdxCurr]; 01354 Quaternion<T> & qn_prev = nextNode.Orientation[IdxPrev]; 01355 Quaternion<T> qn_v = ( qn_prev - qn ) * inv_timestep; 01356 --iterNode; // return to the current position 01357 01358 Quaternion<T> qqn = q + qn; 01359 Quaternion<T> qqn_v = q_v + qn_v; 01360 T Is = m_Parameters.MaterialDensity * Math<T>::PI * m_Parameters.Radius*m_Parameters.Radius; 01361 T k1 = Is*0.25 * B_1(qqn).InnerProduct(qqn_v); 01362 T k2 = Is*0.25 * B_2(qqn).InnerProduct(qqn_v); 01363 T k3 = Is*0.5 * B_3(qqn).InnerProduct(qqn_v); 01364 T s = m_Parameters.LinkLength * 0.25 * ( m_Parameters.Kr[0]*k1 + m_Parameters.Kr[1]*k2 + m_Parameters.Kr[2]*k3 ); 01365 01366 Quaternion<T> Q( 01367 -q.GetI() - q_v.GetI() - qn_v.GetI() - qn.GetI(), 01368 q.GetR() + q_v.GetR() + qn_v.GetR() + qn.GetR(), 01369 q.GetK() + q_v.GetK() + qn_v.GetK() + qn.GetK(), 01370 q.GetJ() - q_v.GetJ() - qn_v.GetJ() - qn.GetJ() 01371 ); 01372 Q *= s; 01373 currNode.Torque -= Q; 01374 nextNode.Torque -= Q; 01375 } 01376 #endif//USE_CORDE_SIM 01377 01378 01379 // Compute the constraint force of both centerlines and a quaternion 01380 template <typename T> 01381 void ModelElasticRod<T>::ComputeConstraintForceOfCenterlineAndOrientation ( 01382 typename SetOfElasticRodNodes::iterator & iterNode ) 01383 { 01384 // Current node {j} 01385 ElasticRodNode<T> & currNode = *iterNode; 01386 // Next Node {j+1} 01387 ElasticRodNode<T> & nextNode = *(++iterNode); 01388 --iterNode; // return to the current position 01389 01390 PointMass<T> & R = currNode.Centerline[IdxCurr]; // current centerline 01391 PointMass<T> & Rn = nextNode.Centerline[IdxCurr]; // next centerline 01392 Quaternion<T> & Q = currNode.Orientation[IdxCurr]; // the (current) orientation sitting between the current and next centerlines 01393 01394 Vector3<T> Rn_R ( Rn.GetPosition() - R.GetPosition() ); 01395 T rn_r_len_square = Rn_R.SquaredLength(); 01396 T rn_r_len = sqrt( rn_r_len_square ); 01397 01398 // rest_len * Kappa * ( (r_{i+1}-r_{i})/||r_{i+1}-r_{i}|| - d3(q_{i}) ) 01399 Vector3<T> Vc = currNode.CenterlineRestLength * m_Parameters.Kconstraint_3rdDirAlignTangent * ( Rn_R/rn_r_len - Get3rdDirector(Q) ); 01400 01401 // Compute the constraint force (torque) for the quaternion 01402 Vector3<T> Vc2 = Vc * 2; 01403 Quaternion<T> cTorque_q ( 01404 Vc2 * Vector3<T>( Q.GetJ(), -Q.GetI(), Q.GetR() ), 01405 Vc2 * Vector3<T>( Q.GetK(), -Q.GetR(), -Q.GetI() ), 01406 Vc2 * Vector3<T>( Q.GetR(), Q.GetK(), -Q.GetJ() ), 01407 Vc2 * Vector3<T>( Q.GetI(), Q.GetJ(), Q.GetK() ) 01408 ); 01409 // Add the constraint torque to the total torque 01410 currNode.Torque += cTorque_q; 01411 01412 // Compute the constraint force for both centerlines 01413 // The sum of the constaint forces at r_{i} and r_{i+1} is zero. 01414 Vector3<T> Vcr = Vc / ( rn_r_len_square * rn_r_len ); 01415 T xd = Rn_R.GetX(), yd = Rn_R.GetY(), zd = Rn_R.GetZ(); 01416 T xd_yd = xd * yd; 01417 T xd_zd = xd * zd; 01418 T yd_zd = yd * zd; 01419 Vector3<T> cForce_r ( 01420 Vcr * Vector3<T>( rn_r_len_square - xd*xd, -xd_yd, -xd_zd ), 01421 Vcr * Vector3<T>( -xd_yd, rn_r_len_square - yd*yd, -yd_zd ), 01422 Vcr * Vector3<T>( -xd_zd, -yd_zd, rn_r_len_square - zd*zd ) 01423 ); 01424 01425 currNode.Centerline[IdxCurr].SetForce( currNode.Centerline[IdxCurr].GetForce() + cForce_r ); 01426 nextNode.Centerline[IdxCurr].SetForce( nextNode.Centerline[IdxCurr].GetForce() - cForce_r ); 01427 } 01428 01429 // Return the quaternion resulted by B_1 * a quaternion 01430 template <typename T> 01431 Quaternion<T> ModelElasticRod<T>::B_1 ( Quaternion<T> const & q ) const 01432 { 01433 // Quaternions in the CoRdE model is <i,j,k,r> 01434 // | 0 0 0 1 | |i| 01435 // B_1 = | 0 0 1 0 | |j| 01436 // | 0 -1 0 0 | |k| 01437 // | -1 0 0 0 | |r| 01438 // So it has to be converted to fit our quaternion <r,i,j,k> 01439 // by first remove the last column and add it back as the first column, 01440 // then remove the last row and add it back as the first row. 01441 // | 0 -1 0 0 | |r| |-i| 01442 // | 1 0 0 0 | |i| | r| 01443 // B_1 = | 0 0 0 1 | |j| = | k| 01444 // | 0 0 -1 0 | |k| |-j| 01445 return Quaternion<T>( -q.GetI(), q.GetR(), q.GetK(), -q.GetJ() ); 01446 } 01447 01448 // Return the quaternion resulted by B_2 * a quaternion 01449 template <typename T> 01450 Quaternion<T> ModelElasticRod<T>::B_2 ( Quaternion<T> const & q ) const 01451 { 01452 // Quaternions in the CoRdE model is <i,j,k,r> 01453 // | 0 0 -1 0 | |i| 01454 // B_2 = | 0 0 0 1 | |j| 01455 // | 1 0 0 0 | |k| 01456 // | 0 -1 0 0 | |r| 01457 // So it has to be converted to fit our quaternion <r,i,j,k> 01458 // by first remove the last column and add it back as the first column, 01459 // then remove the last row and add it back as the first row. 01460 // | 0 0 -1 0 | |r| |-j| 01461 // | 0 0 0 -1 | |i| |-k| 01462 // B_2 = | 1 0 0 0 | |j| = | r| 01463 // | 0 1 0 0 | |k| | i| 01464 return Quaternion<T>( -q.GetJ(), -q.GetK(), q.GetR(), q.GetI() ); 01465 } 01466 01467 // Return the quaternion resulted by B_3 * a quaternion 01468 template <typename T> 01469 Quaternion<T> ModelElasticRod<T>::B_3 ( Quaternion<T> const & q ) const 01470 { 01471 // Quaternions in the CoRdE model is <i,j,k,r> 01472 // | 0 1 0 0 | |i| 01473 // B_3 = | -1 0 0 0 | |j| 01474 // | 0 0 0 1 | |k| 01475 // | 0 0 -1 0 | |r| 01476 // So it has to be converted to fit our quaternion <r,i,j,k> 01477 // by first remove the last column and add it back as the first column, 01478 // then remove the last row and add it back as the first row. 01479 // | 0 0 0 -1 | |r| |-k| 01480 // | 0 0 1 0 | |i| | j| 01481 // B_3 = | 0 -1 0 0 | |j| = |-i| 01482 // | 1 0 0 0 | |k| | r| 01483 return Quaternion<T>( -q.GetK(), q.GetJ(), -q.GetI(), q.GetR() ); 01484 } 01485 01486 // Return the quaternion resulted by B0_1 * a quaternion 01487 template <typename T> 01488 Quaternion<T> ModelElasticRod<T>::B0_1 ( Quaternion<T> const & q ) const 01489 { 01490 // Quaternions in the CoRdE model is <i,j,k,r> 01491 // | 0 0 0 1 | |i| 01492 // B0_1 = | 0 0 -1 0 | |j| 01493 // | 0 1 0 0 | |k| 01494 // | -1 0 0 0 | |r| 01495 // So it has to be converted to fit our quaternion <r,i,j,k> 01496 // by first remove the last column and add it back as the first column, 01497 // then remove the last row and add it back as the first row. 01498 // | 0 -1 0 0 | |r| |-i| 01499 // | 1 0 0 0 | |i| | r| 01500 // B0_1 = | 0 0 0 -1 | |j| = |-k| 01501 // | 0 0 1 0 | |k| | j| 01502 return Quaternion<T>( -q.GetI(), q.GetR(), -q.GetK(), q.GetJ() ); 01503 } 01504 01505 // Return the quaternion resulted by B0_2 * a quaternion 01506 template <typename T> 01507 Quaternion<T> ModelElasticRod<T>::B0_2 ( Quaternion<T> const & q ) const 01508 { 01509 // Quaternions in the CoRdE model is <i,j,k,r> 01510 // | 0 0 1 0 | |i| 01511 // B0_2 = | 0 0 0 1 | |j| 01512 // | -1 0 0 0 | |k| 01513 // | 0 -1 0 0 | |r| 01514 // So it has to be converted to fit our quaternion <r,i,j,k> 01515 // by first remove the last column and add it back as the first column, 01516 // then remove the last row and add it back as the first row. 01517 // | 0 0 -1 0 | |r| |-j| 01518 // | 0 0 0 1 | |i| | k| 01519 // B0_2 = | 1 0 0 0 | |j| = | r| 01520 // | 0 -1 0 0 | |k| |-i| 01521 return Quaternion<T>( -q.GetJ(), q.GetK(), q.GetR(), -q.GetI() ); 01522 } 01523 01524 // Return the quaternion resulted by B0_3 * a quaternion 01525 template <typename T> 01526 Quaternion<T> ModelElasticRod<T>::B0_3 ( Quaternion<T> const & q ) const 01527 { 01528 // Quaternions in the CoRdE model is <i,j,k,r> 01529 // | 0 -1 0 0 | |i| 01530 // B0_3 = | 1 0 0 0 | |j| 01531 // | 0 0 0 1 | |k| 01532 // | 0 0 -1 0 | |r| 01533 // So it has to be converted to fit our quaternion <r,i,j,k> 01534 // by first remove the last column and add it back as the first column, 01535 // then remove the last row and add it back as the first row. 01536 // | 0 0 0 -1 | |r| |-k| 01537 // | 0 0 -1 0 | |i| |-j| 01538 // B0_3 = | 0 1 0 0 | |j| = | i| 01539 // | 1 0 0 0 | |k| | r| 01540 return Quaternion<T>( -q.GetK(), -q.GetJ(), q.GetI(), q.GetR() ); 01541 } 01542 01543 /* 01544 // Get the k-th director from a rotation matrix 01545 template <typename T> 01546 Vector3<T> ModelElasticRod<T>::GetDirector ( int directorNumber, Matrix3x3<T> const & R ) const 01547 { 01548 // The k-th director of the j-th material frame is obtained as 01549 // the k-th column of the rotation matrix R_j. 01550 // Here k is zero-based. 01551 assert( 0 <= directorNumber && directorNumber <= 2 ); 01552 return Vector3<T>( R(directorNumber,0), R(directorNumber,1), R(directorNumber,2) ); 01553 } 01554 //*/ 01555 01556 // Get the 1st director from a quaternion 01557 template <typename T> 01558 Vector3<T> ModelElasticRod<T>::Get1stDirector ( Quaternion<T> const & q ) const 01559 { 01560 // The k-th director of the j-th material frame is obtained as 01561 // the k-th column of the rotation matrix R_j. 01562 // Here k is zero-based. 01563 01564 // The rotation matrix from a quaternion can be obtained with this formula 01565 //Matrix3x3<T>( 01566 // rr+ii-jj-kk, 2*(ij-rk), 2*(ik+rj), 01567 // 2*(ij+rk), rr-ii+jj-kk, 2*(jk-ri), 01568 // 2*(ik-rj), 2*(jk+ri), rr-ii-jj+kk 01569 // ); 01570 return Vector3<T>( 01571 q.GetR()*q.GetR() + q.GetI()*q.GetI() - q.GetJ()*q.GetJ() - q.GetK()*q.GetK(), 01572 2*(q.GetI()*q.GetJ() + q.GetR()*q.GetK()), 01573 2*(q.GetI()*q.GetK() - q.GetR()*q.GetJ()) 01574 ); 01575 } 01576 01577 // Get the 2nd director from a quaternion 01578 template <typename T> 01579 Vector3<T> ModelElasticRod<T>::Get2ndDirector ( Quaternion<T> const & q ) const 01580 { 01581 // The k-th director of the j-th material frame is obtained as 01582 // the k-th column of the rotation matrix R_j. 01583 // Here k is zero-based. 01584 01585 // The rotation matrix from a quaternion can be obtained with this formula 01586 //Matrix3x3<T>( 01587 // rr+ii-jj-kk, 2*(ij-rk), 2*(ik+rj), 01588 // 2*(ij+rk), rr-ii+jj-kk, 2*(jk-ri), 01589 // 2*(ik-rj), 2*(jk+ri), rr-ii-jj+kk 01590 // ); 01591 return Vector3<T>( 01592 2*(q.GetI()*q.GetJ() - q.GetR()*q.GetK()), 01593 q.GetR()*q.GetR() - q.GetI()*q.GetI() + q.GetJ()*q.GetJ() - q.GetK()*q.GetK(), 01594 2*(q.GetJ()*q.GetK() + q.GetR()*q.GetI()) 01595 ); 01596 } 01597 01598 // Get the 3rd director from a quaternion 01599 template <typename T> 01600 Vector3<T> ModelElasticRod<T>::Get3rdDirector ( Quaternion<T> const & q ) const 01601 { 01602 // The k-th director of the j-th material frame is obtained as 01603 // the k-th column of the rotation matrix R_j. 01604 // Here k is zero-based. 01605 01606 // The rotation matrix from a quaternion can be obtained with this formula 01607 //Matrix3x3<T>( 01608 // rr+ii-jj-kk, 2*(ij-rk), 2*(ik+rj), 01609 // 2*(ij+rk), rr-ii+jj-kk, 2*(jk-ri), 01610 // 2*(ik-rj), 2*(jk+ri), rr-ii-jj+kk 01611 // ); 01612 return Vector3<T>( 01613 2*(q.GetI()*q.GetK() + q.GetR()*q.GetJ()), 01614 2*(q.GetJ()*q.GetK() - q.GetR()*q.GetI()), 01615 q.GetR()*q.GetR() - q.GetI()*q.GetI() - q.GetJ()*q.GetJ() + q.GetK()*q.GetK() 01616 ); 01617 } 01618 01620 template <typename T> 01621 Quaternion<T> ModelElasticRod<T>::u_1_LocFrame ( 01622 Quaternion<T> const & q, // the current quaternion 01623 Quaternion<T> const & q_ds, // the spatial derivative of the current quaternion 01624 T scale // the scale should be 2/||quaternion||^2 01625 ) 01626 { 01627 return Quaternion<T>( B_1(q) * q_ds * scale ); 01628 } 01629 01631 template <typename T> 01632 Quaternion<T> ModelElasticRod<T>::u_2_LocFrame ( 01633 Quaternion<T> const & q, // the current quaternion 01634 Quaternion<T> const & q_ds, // the spatial derivative of the current quaternion 01635 T scale // the scale should be 2/||quaternion||^2 01636 ) 01637 { 01638 return Quaternion<T>( B_2(q) * q_ds * scale ); 01639 } 01640 01642 template <typename T> 01643 Quaternion<T> ModelElasticRod<T>::u_3_LocFrame ( 01644 Quaternion<T> const & q, // the current quaternion 01645 Quaternion<T> const & q_ds, // the spatial derivative of the current quaternion 01646 T scale // the scale should be 2/||quaternion||^2 01647 ) 01648 { 01649 return Quaternion<T>( B_3(q) * q_ds * scale ); 01650 } 01651 01653 template <typename T> 01654 Quaternion<T> ModelElasticRod<T>::omega_1_LocFrame ( 01655 Quaternion<T> const & q, // the current quaternion 01656 Quaternion<T> const & q_dt, // the time derivative of the current quaternion 01657 T scale // the scale should be 2/||quaternion||^2 01658 ) 01659 { 01660 return Quaternion<T>( B_1(q) * q_dt * scale ); 01661 } 01662 01664 template <typename T> 01665 Quaternion<T> ModelElasticRod<T>::omega_2_LocFrame ( 01666 Quaternion<T> const & q, // the current quaternion 01667 Quaternion<T> const & q_dt, // the time derivative of the current quaternion 01668 T scale // the scale should be 2/||quaternion||^2 01669 ) 01670 { 01671 return Quaternion<T>( B_2(q) * q_dt * scale ); 01672 } 01673 01675 template <typename T> 01676 Quaternion<T> ModelElasticRod<T>::omega_3_LocFrame ( 01677 Quaternion<T> const & q, // the current quaternion 01678 Quaternion<T> const & q_dt, // the time derivative of the current quaternion 01679 T scale // the scale should be 2/||quaternion||^2 01680 ) 01681 { 01682 return Quaternion<T>( B_3(q) * q_dt * scale ); 01683 } 01684 01686 template <typename T> 01687 Quaternion<T> ModelElasticRod<T>::omega0_1_RefFrame ( 01688 Quaternion<T> const & q, // the current quaternion 01689 Quaternion<T> const & q_dt, // the time derivative of the current quaternion 01690 T scale // the scale should be 2/||quaternion||^2 01691 ) 01692 { 01693 return Quaternion<T>( B0_1(q) * q_dt * scale ); 01694 } 01695 01697 template <typename T> 01698 Quaternion<T> ModelElasticRod<T>::omega0_2_RefFrame ( 01699 Quaternion<T> const & q, // the current quaternion 01700 Quaternion<T> const & q_dt, // the time derivative of the current quaternion 01701 T scale // the scale should be 2/||quaternion||^2 01702 ) 01703 { 01704 return Quaternion<T>( B0_2(q) * q_dt * scale ); 01705 } 01706 01708 template <typename T> 01709 Quaternion<T> ModelElasticRod<T>::omega0_3_RefFrame ( 01710 Quaternion<T> const & q, // the current quaternion 01711 Quaternion<T> const & q_dt, // the time derivative of the current quaternion 01712 T scale // the scale should be 2/||quaternion||^2 01713 ) 01714 { 01715 return Quaternion<T>( B0_3(q) * q_dt * scale ); 01716 } 01717 //----------------------------------------------------------------------------- 01718 01719 01720 //============================================================================= 01721 //----------------------------------------------------------------------------- 01722 template <typename T> 01723 int ModelElasticRod<T>::FindTheClosestPointToPoint ( 01724 Vector3<T> const & closeToPoint, 01725 T distance_limit 01726 ) const 01727 { 01728 int iNumPoints = GetNumberOfPoints(); 01729 01730 int iClosestPointNumber = -1; 01731 T tClosestDistance = distance_limit; 01732 T tDistance; 01733 for ( int i = 0; i < iNumPoints; ++i ) { 01734 tDistance = ( closeToPoint - RefToCurrentVertexPositionOfNodeNumber( i ) ).Length(); 01735 if ( tClosestDistance > tDistance ) { 01736 tClosestDistance = tDistance; 01737 iClosestPointNumber = i; 01738 } 01739 } 01740 01741 return iClosestPointNumber; 01742 } 01743 //----------------------------------------------------------------------------- 01744 template <typename T> 01745 bool ModelElasticRod<T>::PickAt ( 01746 Vector3<T> const & closeToPoint, 01747 T distance_limit, 01748 int & pickedID 01749 ) 01750 { 01751 pickedID = FindTheClosestPointToPoint( closeToPoint, distance_limit ); 01752 if ( pickedID < 0 ) return false; 01753 m_Nodes[ pickedID ].UseEnforcedPosition = true; 01754 m_Nodes[ pickedID ].SimFlags.ClearSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 01755 return true; 01756 } 01757 //----------------------------------------------------------------------------- 01758 template <typename T> 01759 void ModelElasticRod<T>::PickPoint ( 01760 int pickedID 01761 ) 01762 { 01763 assert( 0 <= pickedID && pickedID < GetNumberOfPoints() ); 01764 01765 //if ( 0 <= pickedID && pickedID < GetNumberOfPoints() ) { 01766 m_Nodes[ pickedID ].UseEnforcedPosition = true; 01767 m_Nodes[ pickedID ].SimFlags.ClearSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 01768 //} 01769 } 01770 //----------------------------------------------------------------------------- 01771 template <typename T> 01772 void ModelElasticRod<T>::MovePickedPoint ( 01773 int pickedID, 01774 Vector3<T> & position 01775 ) 01776 { 01777 assert( 0 <= pickedID && pickedID < GetNumberOfPoints() ); 01778 //if ( 0 <= pickedID && pickedID < GetNumberOfPoints() ) { 01779 //if ( m_Nodes[ pickedID ].UseEnforcedPosition ) { 01780 m_Nodes[ pickedID ].EnforcedPosition = position; 01781 //} 01782 //} 01783 } 01784 //----------------------------------------------------------------------------- 01785 template <typename T> 01786 void ModelElasticRod<T>::UnpickPoint ( 01787 int pickedID 01788 ) 01789 { 01790 assert( 0 <= pickedID && pickedID < GetNumberOfPoints() ); 01791 //if ( 0 <= pickedID && pickedID < GetNumberOfPoints() ) { 01792 m_Nodes[ pickedID ].UseEnforcedPosition = false; 01793 m_Nodes[ pickedID ].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 01794 //} 01795 } 01796 //============================================================================= 01797 01798 01799 01800 /* 01801 //============================================================================= 01802 #ifdef TAPs_ADD_KNOT_RECOGNITION 01803 //----------------------------------------------------------------------------- 01804 template <typename T> 01805 void ModelElasticRod<T>::ComputeStickPairForce ( typename SetOfElasticRodNodes::iterator & iterNode ) 01806 { 01807 if ( iterNode->StickPairNodeID < 0 ) return; 01808 01809 // Current node 01810 //ElasticRodNode<T> & currNode = *iterNode; 01811 // Next Node 01812 //ElasticRodNode<T> & nextNode = *(++iterNode); 01813 //--iterNode; // return to the current position 01814 01815 // Compute the stick pair force 01816 // F_s = K_s * ( curr_len/rest_len - 1 ) * (nextPtMass-currPtMass)/curr_len 01817 Vector3<T> pB_pA = m_Nodes[iterNode->StickPairNodeID].Centerline[IdxCurr].GetPosition() - iterNode->Centerline[IdxCurr].GetPosition(); 01818 T currLength = pB_pA.Length() - m_Parameters.Radius*2; 01819 T scale = m_Parameters.KstickPair * currLength; 01820 01821 Vector3<T> stickForce = scale * pB_pA; 01822 01823 // Add the stretch force to the nodes' total force 01824 iterNode->Centerline[IdxCurr].SetForce( iterNode->Centerline[IdxCurr].GetForce() + stickForce ); 01825 //m_Nodes[iterNode->StickPairNodeID].Centerline[IdxCurr].SetForce( m_Nodes[iterNode->StickPairNodeID].Centerline[IdxCurr].GetForce() - stickForce ); 01826 } 01827 //----------------------------------------------------------------------------- 01828 #endif//TAPs_ADD_KNOT_RECOGNITION 01829 //============================================================================= 01830 //*/ 01831 01832 01833 01834 #if defined(__gl_h_) || defined(__GL_H__) 01835 //============================================================================= 01836 template <typename T> 01837 void ModelElasticRod<T>::InitGL () 01838 { 01839 ClearGL(); 01840 01841 Rendering.Material.SetEmission( 0, 0, 0, 1 ); 01842 Rendering.Material.SetAmbient( 0.2, 0.4, 0.8, 1 ); 01843 Rendering.Material.SetDiffuse( 0.2, 0.4, 1.0, 1 ); 01844 //Rendering.Material.SetAmbient( 0.9, 0.9, 1.0, 1 ); 01845 //Rendering.Material.SetDiffuse( 0.9, 0.9, 1.0, 1 ); 01846 Rendering.Material.SetSpecular( 1, 1, 1, 1 ); 01847 Rendering.Material.SetShininess( 128 ); 01848 01849 01850 m_drawCrossSectionVertices = new Vector3<T>[m_drawNV]; 01851 m_drawCrossSectionNormals = new Vector3<T>[m_drawNV]; 01852 m_drawCrossSectionTexCoords = new T[m_drawNV]; 01853 01854 vertices = new Vector3<T>*[3]; 01855 normals = new Vector3<T>*[3]; 01856 texCoords = new Vector3<T>*[3]; 01857 for ( int i = 0; i < 3; ++i ) { 01858 vertices[i] = new Vector3<T>[m_drawNV]; 01859 normals[i] = new Vector3<T>[m_drawNV]; 01860 texCoords[i] = new Vector3<T>[m_drawNV]; 01861 } 01862 sVertices = new Vector3<T>[m_drawNV]; 01863 01864 ComputeVerticesAndNormalsOfCircleCrossSection(); 01865 01866 #ifdef TAPs_USE_GLSL 01867 if ( !InitGLSL() ) { 01868 std::cout << "FAILED: Initializing GLSL!" << std::endl; 01869 exit(-1); 01870 } 01871 #endif//TAPs_USE_GLSL 01872 01873 // (m_drawNV * 3) is for the triangle strip 01874 // where m_drawNV is the number of vertices per cross section 01875 // and each link drawing is divided into 3 cross sections 01876 // ------------- 01877 // | /| /| /| /| 01878 // |/ |/ |/ |/ | 01879 // ------------- 01880 // | /| /| /| /| 01881 // |/ |/ |/ |/ | 01882 // ------------- <--- this one is redundant for the next link 01883 m_numOfVertices = (m_Parameters.NumOfNodes-1) * (m_drawNV+1) * 4; 01884 unsigned int size = m_numOfVertices * 4 * 3; // 4 for xyzw; 3 for position, normal, and texture coordinates 01885 m_pVertexData = new GLfloat[size]; 01886 m_NumOfBytesOfVertexData = size * sizeof(GLfloat); 01887 if ( !m_pVertexData ) { 01888 std::cout << "FAILED: Allocating memory for vertex data for drawing by OpenGL!" << std::endl; 01889 exit(-2); 01890 } 01891 01892 glGenBuffers( 1, &m_GLVertexArray ); 01893 glBindBuffer( GL_ARRAY_BUFFER, m_GLVertexArray ); 01894 glBufferData( GL_ARRAY_BUFFER, m_NumOfBytesOfVertexData, NULL, GL_DYNAMIC_DRAW ); 01895 glBindBuffer( GL_ARRAY_BUFFER, 0 ); 01896 01897 #ifdef TAPs_USE_CUDA 01898 { 01899 float * csVertexData = new float[ m_drawNV * 4 * 3 ]; // 4 for xyzw; 3 for V, N, and TC 01900 int idx = 0; 01901 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 01902 csVertexData[idx++] = m_drawCrossSectionVertices[i][0]; 01903 csVertexData[idx++] = m_drawCrossSectionVertices[i][1]; 01904 csVertexData[idx++] = m_drawCrossSectionVertices[i][2]; 01905 csVertexData[idx++] = 1.0f; 01906 } 01907 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 01908 csVertexData[idx++] = m_drawCrossSectionNormals[i][0]; 01909 csVertexData[idx++] = m_drawCrossSectionNormals[i][1]; 01910 csVertexData[idx++] = m_drawCrossSectionNormals[i][2]; 01911 csVertexData[idx++] = 1.0f; 01912 } 01913 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 01914 csVertexData[idx++] = 0.0f; 01915 csVertexData[idx++] = m_drawCrossSectionTexCoords[i]; 01916 csVertexData[idx++] = 0.0f; 01917 csVertexData[idx++] = 1.0f; 01918 } 01919 TAPs::CUDA::GL__InitailizeDataForElasticRodModel_Drawing( m_drawNV, csVertexData, m_GLVertexArray ); 01920 delete [] csVertexData; 01921 } 01922 #endif//TAPs_USE_CUDA 01923 } 01924 01925 01926 template <typename T> 01927 void ModelElasticRod<T>::ClearGL () 01928 { 01929 #ifdef TAPs_USE_CUDA 01930 if ( m_GLVertexArray > 0 ) { 01931 TAPs::CUDA::GL__UnregisterBufferObject( m_GLVertexArray ); 01932 } 01933 #endif//TAPs_USE_CUDA 01934 01935 if ( m_GLVertexArray > 0 ) { 01936 glDeleteBuffers( 1, &m_GLVertexArray ); 01937 m_GLVertexArray = 0; 01938 } 01939 if ( m_pVertexData ) { 01940 delete [] m_pVertexData; 01941 m_pVertexData = NULL; 01942 } 01943 01944 //* 01945 if ( m_drawCrossSectionVertices ) { 01946 delete [] m_drawCrossSectionVertices; 01947 m_drawCrossSectionVertices = NULL; 01948 } 01949 if ( m_drawCrossSectionNormals ) { 01950 delete [] m_drawCrossSectionNormals; 01951 m_drawCrossSectionNormals = NULL; 01952 } 01953 if ( m_drawCrossSectionTexCoords ) { 01954 delete [] m_drawCrossSectionTexCoords; 01955 m_drawCrossSectionTexCoords = NULL; 01956 } 01957 //*/ 01958 01959 //* 01960 if ( vertices ) { 01961 for ( int i = 0; i < 3; ++i ) { 01962 delete [] vertices[i]; 01963 } 01964 delete [] vertices; 01965 vertices = NULL; 01966 } 01967 if ( normals ) { 01968 for ( int i = 0; i < 3; ++i ) { 01969 delete [] normals[i]; 01970 } 01971 delete [] normals; 01972 normals = NULL; 01973 } 01974 if ( texCoords ) { 01975 for ( int i = 0; i < 3; ++i ) { 01976 delete [] texCoords[i]; 01977 } 01978 delete [] texCoords; 01979 texCoords = NULL; 01980 } 01981 if ( sVertices ) { 01982 delete [] sVertices; 01983 sVertices = NULL; 01984 } 01985 //*/ 01986 } 01987 01988 01989 // Set how many vertices per cross section for drawing 01990 template <typename T> 01991 void ModelElasticRod<T>::SetRenderingForNumberOfVerticesPerCrossSection ( unsigned int i ) 01992 { 01993 if ( i < 2 ) i = 2; 01994 else if ( i > 32 ) i = 32; 01995 m_drawNV = i; 01996 ClearGL(); 01997 InitGL(); 01998 } 01999 02000 02001 #ifdef ELASTIC_MODEL_SIMPLEST_DRAW 02002 template <typename T> 02003 void ModelElasticRod<T>::Draw () 02004 { 02005 SetOfElasticRodNodes::const_iterator currNode = m_Nodes.begin(); 02006 02007 Vector3<T> pos1, pos0 = currNode->Centerline[IdxCurr].GetPosition(); 02008 (currNode++)->Centerline[IdxCurr].Draw(); // draw the first point 02009 while ( currNode != m_Nodes.end() ) { 02010 pos1 = currNode->Centerline[IdxCurr].GetPosition(); 02011 02012 // Draw a line connecting the previous point to this point 02013 glBegin( GL_LINES ); 02014 glVertex3fv( pos0.GetDataFloat() ); 02015 glVertex3fv( pos1.GetDataFloat() ); 02016 glEnd(); 02017 02018 pos0 = pos1; 02019 (currNode++)->Centerline[IdxCurr].Draw(); 02020 } 02021 } 02022 #endif//ELASTIC_MODEL_SIMPLEST_DRAW 02023 02024 02025 #ifdef ELASTIC_MODEL_GENERALIZED_CYLINDERS_DRAW 02026 template <typename T> 02027 void ModelElasticRod<T>::Draw () 02028 { 02029 //static Vector3<T> vertices[3][m_drawNV]; // each segment is drawn with three cross sections 02030 //static Vector3<T> normals[3][m_drawNV]; // each segment is drawn with three cross sections 02031 //static Vector3<T> sVertices[m_drawNV]; // scale vertices 02032 02033 SetOfElasticRodNodes::const_iterator currNode = m_Nodes.begin(); 02034 02035 Vector3<T> pos1, pos0 = currNode->Centerline[IdxCurr].GetPosition(), pos2; 02036 Quaternion<T> ori1, ori0 = currNode->Orientation[IdxCurr]; 02037 T scale = m_Parameters.Radius; // radius of generalized cylinder 02038 02039 int count = 1; 02040 ++currNode; // start from the 2nd point 02041 02042 glPushAttrib( GL_ENABLE_BIT ); 02043 glEnable( GL_COLOR_MATERIAL ); 02044 glColor3f( 0, 0.75, 0 ); 02045 while ( ++count < m_Parameters.NumOfNodes ) { 02046 pos1 = currNode->Centerline[IdxCurr].GetPosition(); 02047 ori1 = currNode->Orientation[IdxCurr]; 02048 pos2 = (++currNode)->Centerline[IdxCurr].GetPosition(); 02049 02050 // Draw a line connecting the previous point to this point 02051 glBegin( GL_LINES ); 02052 glVertex3fv( pos0.GetDataFloat() ); 02053 glVertex3fv( pos1.GetDataFloat() ); 02054 glEnd(); 02055 02056 // Get rotation matrices 02057 Matrix4x4<T> rotMat0( ori0.GetRotationMatrix4x4() ); 02058 Matrix4x4<T> rotMat1( ori1.GetRotationMatrix4x4() ); 02059 Matrix4x4<T> rotMatAvg( (rotMat0+rotMat1)/2 ); 02060 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02061 sVertices[i] = scale*m_drawCrossSectionVertices[i]; 02062 } 02063 02064 // Compute the cross section vertices and normals for middle point from pos0 to pos1 02065 Vector3<T> middlePt0( (pos1+pos0)/2 ); 02066 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02067 normals[0][i] = Matrix4x4MultVector3( rotMat0, m_drawCrossSectionNormals[i] ); 02068 vertices[0][i] = Matrix4x4MultVector3( rotMat0, sVertices[i] ) + middlePt0; 02069 } 02070 // Compute the cross section vertices and normals for pos1 02071 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02072 normals[1][i] = Matrix4x4MultVector3( rotMatAvg, m_drawCrossSectionNormals[i] ); 02073 vertices[1][i] = Matrix4x4MultVector3( rotMatAvg, sVertices[i] ) + pos1; 02074 } 02075 // Compute the cross section vertices and normals for middle point from pos1 to pos2 02076 Vector3<T> middlePt1( (pos2+pos1)/2 ); 02077 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02078 normals[2][i] = Matrix4x4MultVector3( rotMat1, m_drawCrossSectionNormals[i] ); 02079 vertices[2][i] = Matrix4x4MultVector3( rotMat1, sVertices[i] ) + middlePt1; 02080 } 02081 02082 // Draw triangle strip from middlePt0 to pos1 02083 glBegin( GL_TRIANGLE_STRIP ); 02084 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02085 glNormal3fv( normals[1][i].GetDataFloat() ); 02086 glVertex3fv( vertices[1][i].GetDataFloat() ); 02087 glNormal3fv( normals[0][i].GetDataFloat() ); 02088 glVertex3fv( vertices[0][i].GetDataFloat() ); 02089 } 02090 glNormal3fv( normals[1][0].GetDataFloat() ); 02091 glVertex3fv( vertices[1][0].GetDataFloat() ); 02092 glNormal3fv( normals[0][0].GetDataFloat() ); 02093 glVertex3fv( vertices[0][0].GetDataFloat() ); 02094 glEnd(); 02095 02096 // Draw triangle strip from pos1 to middlePt1 02097 glBegin( GL_TRIANGLE_STRIP ); 02098 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02099 glNormal3fv( normals[2][i].GetDataFloat() ); 02100 glVertex3fv( vertices[2][i].GetDataFloat() ); 02101 glNormal3fv( normals[1][i].GetDataFloat() ); 02102 glVertex3fv( vertices[1][i].GetDataFloat() ); 02103 } 02104 glNormal3fv( normals[2][0].GetDataFloat() ); 02105 glVertex3fv( vertices[2][0].GetDataFloat() ); 02106 glNormal3fv( normals[1][0].GetDataFloat() ); 02107 glVertex3fv( vertices[1][0].GetDataFloat() ); 02108 glEnd(); 02109 02110 // Next position 02111 pos0 = pos1; 02112 ori0 = ori1; 02113 } 02114 02115 // Draw all points in red color 02116 currNode = m_Nodes.begin(); 02117 glColor3f( 1, 0, 0 ); 02118 while ( currNode != m_Nodes.end() ) { 02119 (currNode++)->Centerline[IdxCurr].Draw(); 02120 } 02121 glPopAttrib(); 02122 } 02123 #endif//ELASTIC_MODEL_GENERALIZED_CYLINDERS_DRAW 02124 02125 02126 #ifdef TAPs_USE_GLSL 02127 template <typename T> 02128 void ModelElasticRod<T>::Draw () 02129 { 02130 glPushAttrib( GL_ALL_ATTRIB_BITS ); 02131 02132 /* 02133 // Draw all collided points in red color 02134 //glDisable( GL_TEXTURE_2D ); 02135 glEnable( GL_COLOR_MATERIAL ); 02136 SetOfElasticRodNodes::const_iterator currNode = m_Nodes.begin(); 02137 currNode = m_Nodes.begin(); 02138 02139 glColor3f( 1, 0, 0 ); 02140 while ( currNode != m_Nodes.end() ) { 02141 02142 // DEBUG 02143 if ( currNode->IsCollide ) 02144 02145 currNode->Centerline[IdxCurr].Draw( 2 ); 02146 ++currNode; 02147 } 02148 //*/ 02149 02150 //DrawOrientations(); 02151 02152 /* 02153 #ifdef TAPs_ADVANCED_SIMULATION 02154 { 02155 // Draw all clustered points in green color 02156 glEnable( GL_COLOR_MATERIAL ); 02157 SetOfElasticRodNodes::const_iterator currNode = m_Nodes.begin(); 02158 currNode = m_Nodes.begin(); 02159 glColor3f( 0, 1, 0 ); 02160 while ( currNode != m_Nodes.end() ) { 02161 if ( currNode->SimFlags.CheckSimulationConstraints( Enum::AddOn::CLUSTERED ) ) 02162 currNode->Centerline[IdxCurr].Draw( 1.5 ); 02163 ++currNode; 02164 } 02165 } 02166 #endif//TAPs_ADVANCED_SIMULATION 02167 //*/ 02168 02169 glPopAttrib(); 02170 02171 02172 02173 // Start rendering the elastic rod 02174 Rendering.glslProgObj->BeginGLSL(); 02175 02176 //glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT ); 02177 glPushAttrib( GL_ALL_ATTRIB_BITS ); 02178 02179 // DEBUG 02180 //m_CD.Draw(); // draw BVH tree 02181 #ifdef TAPs_ADD_KNOT_RECOGNITION 02182 //m_KR.Draw(); // draw knot recognition 02183 #endif//TAPs_ADD_KNOT_RECOGNITION 02184 02185 // Set texture to texture unit 0 02186 #ifdef TAPs_USE_WXWIDGETS 02187 Rendering.Texture.EnableTextureTarget(); 02188 glActiveTexture( GL_TEXTURE0 ); 02189 Rendering.Texture.BindTexture( 0 ); 02190 Rendering.Texture.UseParameters(); 02191 Rendering.glslProgObj->SetUniform1i( "texture", 0 ); 02192 TAPs::OpenGL::Fn::CHECK_GL_ERROR(); 02193 #endif//TAPs_USE_WXWIDGETS 02194 02195 // Set color material 02196 Rendering.Material.ApplyMaterial(); 02197 02198 #if ER_TIMING_RENDERING != 0 02199 // TIMING 02200 static int times = -1; 02201 ++times; 02202 clock_t startTime, endTime; 02203 static clock_t cpu_compV = 0, cpu_drawV = 0; 02204 static clock_t gpu_compV = 0, gpu_drawV = 0; 02205 static bool isFirstRun = true; 02206 #endif 02207 02208 #ifdef TAPs_USE_CUDA 02209 // Use GPU to compute the generalized cylinder to the already mapped OpenGL buffer object 02210 if ( m_Parameters.EnableCUDA_GenDrawData && m_Parameters.EnableCUDA ) 02211 { 02212 #if ER_TIMING_RENDERING != 0 02213 startTime = clock(); // TIMING 02214 #endif 02215 02216 m_CUDA.GenCylinderVertexDataForDrawing( m_GLVertexArray, m_drawNV ); 02217 02218 #if ER_TIMING_RENDERING != 0 02219 endTime = clock(); // TIMING 02220 if ( isFirstRun ) { 02221 isFirstRun = false; 02222 } 02223 else { 02224 gpu_compV += endTime - startTime; // TIMING 02225 } 02226 startTime = clock(); // TIMING 02227 #endif 02228 02229 // Draw by OpenGL 2.1 02230 static GLsizei stride = 12*sizeof(GLfloat); 02231 glEnableClientState( GL_VERTEX_ARRAY ); 02232 glEnableClientState( GL_NORMAL_ARRAY ); 02233 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 02234 glBindBuffer( GL_ARRAY_BUFFER, m_GLVertexArray ); 02235 02236 glVertexPointer( 4, GL_FLOAT, stride, 0 ); 02237 glNormalPointer( GL_FLOAT, stride, (GLubyte*)NULL + 4*sizeof(GLfloat) ); 02238 glTexCoordPointer( 4, GL_FLOAT, stride, (GLubyte*)NULL + 8*sizeof(GLfloat) ); 02239 02240 GLint first = 0; 02241 GLsizei primCount = (m_drawNV+1)*2; 02242 02243 for ( int i = 0; i < (m_Parameters.NumOfNodes-1)*2 - 1; ++i ) { 02244 glDrawArrays( GL_TRIANGLE_STRIP, first, primCount ); 02245 first += primCount; 02246 } 02247 02248 glBindBuffer( GL_ARRAY_BUFFER, 0 ); 02249 glDisableClientState( GL_VERTEX_ARRAY ); 02250 glDisableClientState( GL_NORMAL_ARRAY ); 02251 glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 02252 02253 #if ER_TIMING_RENDERING != 0 02254 endTime = clock(); // TIMING 02255 if ( isFirstRun ) { 02256 isFirstRun = false; 02257 } 02258 else { 02259 gpu_drawV += endTime - startTime; // TIMING 02260 } 02261 #endif 02262 02263 } 02264 else 02265 #endif//TAPs_USE_CUDA 02266 { 02267 // Use CPU to compute the generalized cylinder and send the draw data to OpenGL 02268 #ifdef TAPs_ER_DRAW_WITH_SUBDIVISION 02269 GenAndDrawCylinderVertexData_SUBDIVISION(); 02270 #else //TAPs_ER_DRAW_WITH_SUBDIVISION 02271 GenAndDrawCylinderVertexData(); 02272 #endif//TAPs_ER_DRAW_WITH_SUBDIVISION 02273 } 02274 02275 #if ER_TIMING_RENDERING != 0 02276 TIMING 02277 if ( times == ER_TIMING_RENDERING_STOP ) { 02278 std::cout << "times: " << times << "\n"; 02279 std::cout << "Compute drawing data (CPU) ACC TIME: " << 1000.0 * cpu_compV / CLOCKS_PER_SEC << " ms.\n"; 02280 std::cout << "Compute drawing data (GPU) ACC TIME: " << 1000.0 * gpu_compV / CLOCKS_PER_SEC << " ms.\n"; 02281 std::cout << "Draw by glBegin/glEnd ACC TIME: " << 1000.0 * cpu_drawV / CLOCKS_PER_SEC << " ms.\n"; 02282 std::cout << "Draw by glDrawArrays ACC TIME: " << 1000.0 * gpu_drawV / CLOCKS_PER_SEC << " ms.\n"; 02283 std::cout << std::endl; 02284 exit(-1); 02285 } 02286 #endif 02287 02288 /* 02289 // DEBUG 02290 // Draw the texture 02291 { 02292 GLfloat s = 0.5; 02293 glBegin( GL_QUADS ); 02294 glNormal3f( 0, 0, 1 ); 02295 glTexCoord3f( 0, 0, 0 ); 02296 glVertex3f( -s, -s, 0 ); 02297 glNormal3f( 0, 0, 1 ); 02298 glTexCoord3f( 1, 0, 0 ); 02299 glVertex3f( s, -s, 0 ); 02300 glNormal3f( 0, 0, 1 ); 02301 glTexCoord3f( 1, 1, 0 ); 02302 glVertex3f( s, s, 0 ); 02303 glNormal3f( 0, 0, 1 ); 02304 glTexCoord3f( 0, 1, 0 ); 02305 glVertex3f( -s, s, 0 ); 02306 glEnd(); 02307 } 02308 //*/ 02309 02310 #ifdef TAPs_USE_WXWIDGETS 02311 Rendering.Texture.UnbindTexture(); 02312 #endif//TAPs_USE_WXWIDGETS 02313 02314 glPopAttrib(); 02315 02316 Rendering.glslProgObj->EndGLSL(); 02317 } 02318 02319 02320 // Draw Orientations 02321 template <typename T> 02322 void ModelElasticRod<T>::DrawOrientations () const 02323 { 02324 SetOfElasticRodNodes::const_iterator currNode = m_Nodes.begin(); 02325 02326 Vector3<T> pos1, pos0 = currNode->Centerline[IdxCurr].GetPosition(), pos2; 02327 Quaternion<T> ori1, ori0 = currNode->Orientation[IdxCurr]; 02328 T scale = 8*m_Parameters.Radius; // radius of generalized cylinder 02329 02330 // Draw orientation 02331 02332 int count = 1; 02333 ++currNode; // start from the 2nd point 02334 02335 static GLfloat red_color[4] = { 1, 0, 0, 1 }; 02336 static GLfloat green_color[4] = { 0, 1, 0, 1 }; 02337 static GLfloat blue_color[4] = { 0, 0, 1, 1 }; 02338 02339 glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT ); 02340 glDisable( GL_TEXTURE_2D ); 02341 02342 // Set color material 02343 //Rendering.Material.ApplyMaterial(); 02344 02345 glEnable( GL_COLOR_MATERIAL ); 02346 02347 while ( ++count < m_Parameters.NumOfNodes ) { 02348 pos1 = currNode->Centerline[IdxCurr].GetPosition(); 02349 ori1 = currNode->Orientation[IdxCurr]; 02350 pos2 = (++currNode)->Centerline[IdxCurr].GetPosition(); 02351 02352 // Draw a line connecting the previous point to this point 02353 //glColor3f( 0.5, 0.5, 0.5 ); 02354 //glBegin( GL_LINES ); 02355 // glVertex3fv( pos0.GetDataFloat() ); 02356 // glVertex3fv( pos1.GetDataFloat() ); 02357 //glEnd(); 02358 02359 // Get rotation matrices 02360 Matrix4x4<T> rotMat0( ori0.GetRotationMatrix4x4() ); 02361 Matrix4x4<T> rotMat1( ori1.GetRotationMatrix4x4() ); 02362 Matrix4x4<T> rotMatAvg( (rotMat0+rotMat1)/2 ); 02363 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02364 sVertices[i] = scale*m_drawCrossSectionVertices[i]; 02365 } 02366 02367 Vector3<T> middlePt0( (pos1+pos0)/2 ); 02368 Vector3<T> middlePt1( (pos2+pos1)/2 ); 02369 02370 // Draw orientation 02371 /* 02372 // pos0 02373 glLineWidth( 5 ); 02374 glPushMatrix(); 02375 glTranslatef( pos0[0], pos0[1], pos0[2] ); 02376 glMultMatrixf( rotMat0.GetTransposeDataFloat() ); 02377 glScalef( 0.1, 0.1, 0.1 ); 02378 glBegin( GL_LINES ); 02379 glColor3f( 1, 0, 0 ); 02380 glVertex3f( 0, 0, 0 ); 02381 glVertex3f( 1, 0, 0 ); 02382 glColor3f( 0, 1, 0 ); 02383 glVertex3f( 0, 0, 0 ); 02384 glVertex3f( 0, 1, 0 ); 02385 glColor3f( 0, 0, 1 ); 02386 glVertex3f( 0, 0, 0 ); 02387 glVertex3f( 0, 0, 1 ); 02388 glEnd(); 02389 glPopMatrix(); 02390 //*/ 02391 // middle 02392 glLineWidth( 1 ); 02393 glPushMatrix(); 02394 glTranslatef( middlePt0[0], middlePt0[1], middlePt0[2] ); 02395 glMultMatrixf( rotMatAvg.GetTransposeDataFloat() ); 02396 GLfloat s = 0.5; 02397 glScalef( s, s, s ); 02398 02399 glEnable( GL_COLOR_MATERIAL ); 02400 glColor3f( 1, 0, 0 ); 02401 OpenGL::OpenGLUsefulObj<T>::DrawOneHeadArrow( CGMath<T>::VectorX, s ); 02402 glColor3f( 0, 1, 0 ); 02403 OpenGL::OpenGLUsefulObj<T>::DrawOneHeadArrow( CGMath<T>::VectorY, s ); 02404 glColor3f( 0, 0, 1 ); 02405 OpenGL::OpenGLUsefulObj<T>::DrawOneHeadArrow( CGMath<T>::VectorZ, s ); 02406 02407 /* 02408 glBegin( GL_LINES ); 02409 glColor3f( 1, 0, 0 ); 02410 glVertex3f( 0, 0, 0 ); 02411 glVertex3f( 1, 0, 0 ); 02412 glColor3f( 0, 1, 0 ); 02413 glVertex3f( 0, 0, 0 ); 02414 glVertex3f( 0, 1, 0 ); 02415 glColor3f( 0, 0, 1 ); 02416 glVertex3f( 0, 0, 0 ); 02417 glVertex3f( 0, 0, 1 ); 02418 glEnd(); 02419 //*/ 02420 02421 glPopMatrix(); 02422 /* 02423 // pos1 02424 glLineWidth( 5 ); 02425 glPushMatrix(); 02426 glTranslatef( pos1[0], pos1[1], pos1[2] ); 02427 glMultMatrixf( rotMat1.GetTransposeDataFloat() ); 02428 glScalef( 0.1, 0.1, 0.1 ); 02429 glBegin( GL_LINES ); 02430 glColor3f( 1, 0, 0 ); 02431 glVertex3f( 0, 0, 0 ); 02432 glVertex3f( 1, 0, 0 ); 02433 glColor3f( 0, 1, 0 ); 02434 glVertex3f( 0, 0, 0 ); 02435 glVertex3f( 0, 1, 0 ); 02436 glColor3f( 0, 0, 1 ); 02437 glVertex3f( 0, 0, 0 ); 02438 glVertex3f( 0, 0, 1 ); 02439 glEnd(); 02440 glPopMatrix(); 02441 //*/ 02442 02443 // Next position 02444 pos0 = pos1; 02445 ori0 = ori1; 02446 } 02447 glPopAttrib(); 02448 } // END: DrawOrientations () const 02449 02450 02451 // Generate cylinder vextex data and draw the data by OpenGL 02452 template <typename T> 02453 void ModelElasticRod<T>::GenAndDrawCylinderVertexData () 02454 { 02455 SetOfElasticRodNodes::const_iterator currNode = m_Nodes.begin(); 02456 02457 Vector3<T> pos1, pos0 = currNode->Centerline[IdxCurr].GetPosition(), pos2; 02458 Quaternion<T> ori1, ori0 = currNode->Orientation[IdxCurr]; 02459 T scale = m_Parameters.Radius; // radius of generalized cylinder 02460 02461 int count = 1; 02462 ++currNode; // start from the 2nd point 02463 02464 // Scale the cross vertices by the radius 02465 //#pragma omp parallel for 02466 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02467 sVertices[i] = scale*m_drawCrossSectionVertices[i]; 02468 } 02469 02470 while ( ++count < m_Parameters.NumOfNodes ) { 02471 02472 #if ER_TIMING_RENDERING != 0 02473 startTime = clock(); // TIMING 02474 #endif 02475 02476 pos1 = currNode->Centerline[IdxCurr].GetPosition(); 02477 ori1 = currNode->Orientation[IdxCurr]; 02478 pos2 = (++currNode)->Centerline[IdxCurr].GetPosition(); 02479 02480 // Get rotation matrices 02481 Matrix4x4<T> rotMat0( ori0.GetRotationMatrix4x4() ); 02482 Matrix4x4<T> rotMat1( ori1.GetRotationMatrix4x4() ); 02483 Matrix4x4<T> rotMatAvg( (rotMat0+rotMat1)/2 ); 02484 02485 // Compute the cross section vertices, normals, and texture coordinates for middle point from pos0 to pos1 02486 Vector3<T> middlePt0( (pos1+pos0)/2 ); 02487 //#pragma omp parallel for 02488 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02489 texCoords[0][i].SetXYZ( 0.0, m_drawCrossSectionTexCoords[i], 0.0 ); 02490 normals[0][i] = Matrix4x4MultVector3( rotMat0, m_drawCrossSectionNormals[i] ); 02491 vertices[0][i] = Matrix4x4MultVector3( rotMat0, sVertices[i] ) + middlePt0; 02492 } 02493 // Compute the cross section vertices, normals, and texture coordinates for pos1 02494 //#pragma omp parallel for 02495 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02496 texCoords[1][i].SetXYZ( 0.5, m_drawCrossSectionTexCoords[i], 0.0 ); 02497 normals[1][i] = Matrix4x4MultVector3( rotMatAvg, m_drawCrossSectionNormals[i] ); 02498 vertices[1][i] = Matrix4x4MultVector3( rotMatAvg, sVertices[i] ) + pos1; 02499 } 02500 // Compute the cross section vertices, normals, and texture coordinates for middle point from pos1 to pos2 02501 Vector3<T> middlePt1( (pos2+pos1)/2 ); 02502 //#pragma omp parallel for 02503 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02504 texCoords[2][i].SetXYZ( 1.0, m_drawCrossSectionTexCoords[i], 0.0 ); 02505 normals[2][i] = Matrix4x4MultVector3( rotMat1, m_drawCrossSectionNormals[i] ); 02506 vertices[2][i] = Matrix4x4MultVector3( rotMat1, sVertices[i] ) + middlePt1; 02507 } 02508 02509 #if ER_TIMING_RENDERING != 0 02510 endTime = clock(); // TIMING 02511 if ( isFirstRun ) { 02512 isFirstRun = false; 02513 } 02514 else { 02515 cpu_compV += endTime - startTime; // TIMING 02516 } 02517 #endif 02518 02521 //glBegin( GL_TRIANGLE_STRIP ); 02522 // for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02523 // glTexCoord3fv( texCoords[2][i].GetDataFloat() ); 02524 // glNormal3fv( normals[2][i].GetDataFloat() ); 02525 // glVertex3fv( vertices[2][i].GetDataFloat() ); 02526 // glTexCoord3fv( texCoords[0][i].GetDataFloat() ); 02527 // glNormal3fv( normals[0][i].GetDataFloat() ); 02528 // glVertex3fv( vertices[0][i].GetDataFloat() ); 02529 // } 02530 // glTexCoord3fv( texCoords[2][0].GetDataFloat() ); 02531 // glNormal3fv( normals[2][0].GetDataFloat() ); 02532 // glVertex3fv( vertices[2][0].GetDataFloat() ); 02533 // glTexCoord3fv( texCoords[0][0].GetDataFloat() ); 02534 // glNormal3fv( normals[0][0].GetDataFloat() ); 02535 // glVertex3fv( vertices[0][0].GetDataFloat() ); 02536 //glEnd(); 02537 02538 // Two triangle strips from middlePt0 to pos1 and from pos1 to middlePt1 02539 // Draw triangle strip from middlePt0 to pos1 02540 02541 #if ER_TIMING_RENDERING != 0 02542 startTime = clock(); // TIMING 02543 #endif 02544 02545 glBegin( GL_TRIANGLE_STRIP ); 02546 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02547 glTexCoord3fv( texCoords[1][i].GetDataFloat() ); 02548 glNormal3fv( normals[1][i].GetDataFloat() ); 02549 glVertex3fv( vertices[1][i].GetDataFloat() ); 02550 glTexCoord3fv( texCoords[0][i].GetDataFloat() ); 02551 glNormal3fv( normals[0][i].GetDataFloat() ); 02552 glVertex3fv( vertices[0][i].GetDataFloat() ); 02553 } 02554 glTexCoord3fv( texCoords[1][0].GetDataFloat() ); 02555 glNormal3fv( normals[1][0].GetDataFloat() ); 02556 glVertex3fv( vertices[1][0].GetDataFloat() ); 02557 glTexCoord3fv( texCoords[0][0].GetDataFloat() ); 02558 glNormal3fv( normals[0][0].GetDataFloat() ); 02559 glVertex3fv( vertices[0][0].GetDataFloat() ); 02560 glEnd(); 02561 02562 // Draw triangle strip from pos1 to middlePt1 02563 glBegin( GL_TRIANGLE_STRIP ); 02564 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02565 glTexCoord3fv( texCoords[2][i].GetDataFloat() ); 02566 glNormal3fv( normals[2][i].GetDataFloat() ); 02567 glVertex3fv( vertices[2][i].GetDataFloat() ); 02568 glTexCoord3fv( texCoords[1][i].GetDataFloat() ); 02569 glNormal3fv( normals[1][i].GetDataFloat() ); 02570 glVertex3fv( vertices[1][i].GetDataFloat() ); 02571 } 02572 glTexCoord3fv( texCoords[2][0].GetDataFloat() ); 02573 glNormal3fv( normals[2][0].GetDataFloat() ); 02574 glVertex3fv( vertices[2][0].GetDataFloat() ); 02575 glTexCoord3fv( texCoords[1][0].GetDataFloat() ); 02576 glNormal3fv( normals[1][0].GetDataFloat() ); 02577 glVertex3fv( vertices[1][0].GetDataFloat() ); 02578 glEnd(); 02579 02580 #if ER_TIMING_RENDERING != 0 02581 endTime = clock(); // TIMING 02582 if ( isFirstRun ) { 02583 isFirstRun = false; 02584 } 02585 else { 02586 cpu_drawV += endTime - startTime; // TIMING 02587 } 02588 #endif 02589 02590 // Next position 02591 pos0 = pos1; 02592 ori0 = ori1; 02593 } 02594 } 02595 02596 02597 //----------------------------------------------------------------------------- 02598 #ifdef TAPs_ER_DRAW_WITH_SUBDIVISION 02599 //----------------------------------------------------------------------------- 02600 02601 // Generate cylinder vextex data (with Chaikin's algorithm) and draw the data by OpenGL 02602 template <typename T> 02603 void ModelElasticRod<T>::GenAndDrawCylinderVertexData_SUBDIVISION () 02604 { 02605 // Every time 02606 // P_i ------------------------------ P_j 02607 // P_i ----- Q_i ----------- R_i ---- P_j 02608 // Q_i = 0.75*P_i + 0.25P_j 02609 // R_i = 0.25*P_i + 0.75P_j 02610 // 02611 // Level #Pts Kept (computed pts) 02612 // 0 0 0 Level 0 is the original control points 02613 // 1 2 1 1st subdivision (#Pts = 0 + 2) 02614 // 2 6 2 2nd subdivision (#Pts = 2 + 4) 02615 // 3 14 3 3rd subdivision (#Pts = 6 + 8) 02616 // 4 30 4 3rd subdivision (#Pts = 14 + 16) 02617 02618 static const unsigned int level = 2; 02619 static const unsigned int sizePts = ( 2 << (level+1) ) - 2; 02620 static Vector3<T> posKept[level]; 02621 static Matrix4x4<T> rotMatKept[level]; 02622 static Vector3<T> posPts[sizePts]; 02623 static Matrix4x4<T> rotMatPts[sizePts]; 02624 02625 SetOfElasticRodNodes::const_iterator currNode = m_Nodes.begin(); 02626 02627 Vector3<T> pos1, pos0 = currNode->Centerline[IdxCurr].GetPosition(), pos2; 02628 Quaternion<T> ori1, ori0 = currNode->Orientation[IdxCurr]; 02629 T scale = m_Parameters.Radius; // radius of generalized cylinder 02630 02631 //scale *= 2; 02632 02633 int count = 1; 02634 ++currNode; // start from the 2nd point 02635 02636 // Scale the cross section vertices by the radius 02637 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02638 sVertices[i] = scale*m_drawCrossSectionVertices[i]; 02639 } 02640 02641 // Initialize the kept data 02642 for ( int i = 0; i < level; ++i ) { 02643 posKept[i] = pos0; 02644 rotMatKept[i] = ori0.GetRotationMatrix4x4(); 02645 } 02646 02647 while ( ++count < m_Parameters.NumOfNodes ) { 02648 02649 // Get positions and orientations 02650 pos1 = currNode->Centerline[IdxCurr].GetPosition(); 02651 ori1 = currNode->Orientation[IdxCurr]; 02652 pos2 = (++currNode)->Centerline[IdxCurr].GetPosition(); 02653 // Get rotation matrices 02654 Matrix4x4<T> rotMat0( ori0.GetRotationMatrix4x4() ); 02655 Matrix4x4<T> rotMat1( ori1.GetRotationMatrix4x4() ); 02656 // Get positions in the middles (i.e. the orientation positions) 02657 Vector3<T> midPt0( (pos1+pos0)/2 ); 02658 Vector3<T> midPt1( (pos2+pos1)/2 ); 02659 02660 /* 02661 // Generate level 1 02662 GenAndDrawCylinderVertexData_SUBDIVISION_Chaikin_Pts( midPt0, rotMat0, midPt1, rotMat1, posPts[0], rotMatPts[0], posPts[1], rotMatPts[1] ); 02663 // Draw level 1 02664 GenAndDrawCylinderVertexData_SUBDIVISION_Draw( posKept[0], rotMatKept[0], posPts[0], rotMatPts[0], 0.0, 0.5 ); 02665 GenAndDrawCylinderVertexData_SUBDIVISION_Draw( posPts[0], rotMatPts[0], posPts[1], rotMatPts[1], 0.5, 1.0 ); 02666 // Next position 02667 posKept[0] = posPts[1]; 02668 rotMatKept[0] = rotMatPts[1]; 02669 //*/ 02670 02671 02672 //if ( count <= 10 || count >= 50 ) 02673 { 02674 // Generate level 1 02675 GenAndDrawCylinderVertexData_SUBDIVISION_Chaikin_Pts( midPt0, rotMat0, midPt1, rotMat1, posPts[0], rotMatPts[0], posPts[1], rotMatPts[1] ); 02676 // Generate level 2 02677 GenAndDrawCylinderVertexData_SUBDIVISION_Chaikin_Pts( posKept[0], rotMatKept[0], posPts[0], rotMatPts[0], posPts[2], rotMatPts[2], posPts[3], rotMatPts[3] ); 02678 GenAndDrawCylinderVertexData_SUBDIVISION_Chaikin_Pts( posPts[0], rotMatPts[0], posPts[1], rotMatPts[1], posPts[4], rotMatPts[4], posPts[5], rotMatPts[5] ); 02679 // Draw level 2 02680 GenAndDrawCylinderVertexData_SUBDIVISION_Draw( posKept[1], rotMatKept[1], posPts[2], rotMatPts[2], 0.0, 0.25 ); 02681 GenAndDrawCylinderVertexData_SUBDIVISION_Draw( posPts[2], rotMatPts[2], posPts[3], rotMatPts[3], 0.25, 0.5 ); 02682 GenAndDrawCylinderVertexData_SUBDIVISION_Draw( posPts[3], rotMatPts[3], posPts[4], rotMatPts[4], 0.5, 0.75 ); 02683 GenAndDrawCylinderVertexData_SUBDIVISION_Draw( posPts[4], rotMatPts[4], posPts[5], rotMatPts[5], 0.75, 1.0 ); 02684 02685 /* 02686 // DEBUG -- TEST DRAWING 02687 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02688 sVertices[i] *= 1.05; 02689 } 02690 //*/ 02691 02692 } 02693 02694 // Next position 02695 posKept[0] = posPts[1]; 02696 rotMatKept[0] = rotMatPts[1]; 02697 posKept[1] = posPts[5]; 02698 rotMatKept[1] = rotMatPts[5]; 02699 02700 pos0 = pos1; 02701 ori0 = ori1; 02702 } 02703 02704 02705 02706 02707 02708 02709 02710 02711 02712 //SetOfElasticRodNodes::const_iterator currNode = m_Nodes.begin(); 02713 //Vector3<T> pos1, pos0 = currNode->Centerline[IdxCurr].GetPosition(), pos2; 02714 //Quaternion<T> ori1, ori0 = currNode->Orientation[IdxCurr]; 02715 //T scale = m_Parameters.Radius; // radius of generalized cylinder 02716 //int count = 1; 02717 //++currNode; // start from the 2nd point 02718 02719 /* 02720 currNode = m_Nodes.begin(); 02721 pos0 = currNode->Centerline[IdxCurr].GetPosition(); 02722 ori0 = currNode->Orientation[IdxCurr]; 02723 scale = m_Parameters.Radius; // radius of generalized cylinder 02724 count = 1; 02725 ++currNode; // start from the 2nd point 02726 02727 // Scale the cross section vertices by the radius 02728 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02729 sVertices[i] = scale*m_drawCrossSectionVertices[i]; 02730 } 02731 02732 while ( ++count < m_Parameters.NumOfNodes ) { 02733 02734 #if ER_TIMING_RENDERING != 0 02735 startTime = clock(); // TIMING 02736 #endif 02737 02738 pos1 = currNode->Centerline[IdxCurr].GetPosition(); 02739 ori1 = currNode->Orientation[IdxCurr]; 02740 pos2 = (++currNode)->Centerline[IdxCurr].GetPosition(); 02741 02742 // Get rotation matrices 02743 Matrix4x4<T> rotMat0( ori0.GetRotationMatrix4x4() ); 02744 Matrix4x4<T> rotMat1( ori1.GetRotationMatrix4x4() ); 02745 Matrix4x4<T> rotMatAvg( (rotMat0+rotMat1)/2 ); 02746 //#pragma omp parallel for 02747 02748 // Compute the cross section vertices, normals, and texture coordinates for middle point from pos0 to pos1 02749 Vector3<T> middlePt0( (pos1+pos0)/2 ); 02750 //#pragma omp parallel for 02751 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02752 texCoords[0][i].SetXYZ( 0.0, m_drawCrossSectionTexCoords[i], 0.0 ); 02753 normals[0][i] = Matrix4x4MultVector3( rotMat0, m_drawCrossSectionNormals[i] ); 02754 vertices[0][i] = Matrix4x4MultVector3( rotMat0, sVertices[i] ) + middlePt0; 02755 } 02756 // Compute the cross section vertices, normals, and texture coordinates for pos1 02757 //#pragma omp parallel for 02758 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02759 texCoords[1][i].SetXYZ( 0.5, m_drawCrossSectionTexCoords[i], 0.0 ); 02760 normals[1][i] = Matrix4x4MultVector3( rotMatAvg, m_drawCrossSectionNormals[i] ); 02761 vertices[1][i] = Matrix4x4MultVector3( rotMatAvg, sVertices[i] ) + pos1; 02762 } 02763 // Compute the cross section vertices, normals, and texture coordinates for middle point from pos1 to pos2 02764 Vector3<T> middlePt1( (pos2+pos1)/2 ); 02765 //#pragma omp parallel for 02766 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02767 texCoords[2][i].SetXYZ( 1.0, m_drawCrossSectionTexCoords[i], 0.0 ); 02768 normals[2][i] = Matrix4x4MultVector3( rotMat1, m_drawCrossSectionNormals[i] ); 02769 vertices[2][i] = Matrix4x4MultVector3( rotMat1, sVertices[i] ) + middlePt1; 02770 } 02771 02772 #if ER_TIMING_RENDERING != 0 02773 endTime = clock(); // TIMING 02774 if ( isFirstRun ) { 02775 isFirstRun = false; 02776 } 02777 else { 02778 cpu_compV += endTime - startTime; // TIMING 02779 } 02780 #endif 02781 02784 //glBegin( GL_TRIANGLE_STRIP ); 02785 // for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02786 // glTexCoord3fv( texCoords[2][i].GetDataFloat() ); 02787 // glNormal3fv( normals[2][i].GetDataFloat() ); 02788 // glVertex3fv( vertices[2][i].GetDataFloat() ); 02789 // glTexCoord3fv( texCoords[0][i].GetDataFloat() ); 02790 // glNormal3fv( normals[0][i].GetDataFloat() ); 02791 // glVertex3fv( vertices[0][i].GetDataFloat() ); 02792 // } 02793 // glTexCoord3fv( texCoords[2][0].GetDataFloat() ); 02794 // glNormal3fv( normals[2][0].GetDataFloat() ); 02795 // glVertex3fv( vertices[2][0].GetDataFloat() ); 02796 // glTexCoord3fv( texCoords[0][0].GetDataFloat() ); 02797 // glNormal3fv( normals[0][0].GetDataFloat() ); 02798 // glVertex3fv( vertices[0][0].GetDataFloat() ); 02799 //glEnd(); 02800 02801 // Two triangle strips from middlePt0 to pos1 and from pos1 to middlePt1 02802 // Draw triangle strip from middlePt0 to pos1 02803 02804 #if ER_TIMING_RENDERING != 0 02805 startTime = clock(); // TIMING 02806 #endif 02807 02808 glBegin( GL_TRIANGLE_STRIP ); 02809 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02810 glTexCoord3fv( texCoords[1][i].GetDataFloat() ); 02811 glNormal3fv( normals[1][i].GetDataFloat() ); 02812 glVertex3fv( vertices[1][i].GetDataFloat() ); 02813 glTexCoord3fv( texCoords[0][i].GetDataFloat() ); 02814 glNormal3fv( normals[0][i].GetDataFloat() ); 02815 glVertex3fv( vertices[0][i].GetDataFloat() ); 02816 } 02817 glTexCoord3fv( texCoords[1][0].GetDataFloat() ); 02818 glNormal3fv( normals[1][0].GetDataFloat() ); 02819 glVertex3fv( vertices[1][0].GetDataFloat() ); 02820 glTexCoord3fv( texCoords[0][0].GetDataFloat() ); 02821 glNormal3fv( normals[0][0].GetDataFloat() ); 02822 glVertex3fv( vertices[0][0].GetDataFloat() ); 02823 glEnd(); 02824 02825 // Draw triangle strip from pos1 to middlePt1 02826 glBegin( GL_TRIANGLE_STRIP ); 02827 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02828 glTexCoord3fv( texCoords[2][i].GetDataFloat() ); 02829 glNormal3fv( normals[2][i].GetDataFloat() ); 02830 glVertex3fv( vertices[2][i].GetDataFloat() ); 02831 glTexCoord3fv( texCoords[1][i].GetDataFloat() ); 02832 glNormal3fv( normals[1][i].GetDataFloat() ); 02833 glVertex3fv( vertices[1][i].GetDataFloat() ); 02834 } 02835 glTexCoord3fv( texCoords[2][0].GetDataFloat() ); 02836 glNormal3fv( normals[2][0].GetDataFloat() ); 02837 glVertex3fv( vertices[2][0].GetDataFloat() ); 02838 glTexCoord3fv( texCoords[1][0].GetDataFloat() ); 02839 glNormal3fv( normals[1][0].GetDataFloat() ); 02840 glVertex3fv( vertices[1][0].GetDataFloat() ); 02841 glEnd(); 02842 02843 #if ER_TIMING_RENDERING != 0 02844 endTime = clock(); // TIMING 02845 if ( isFirstRun ) { 02846 isFirstRun = false; 02847 } 02848 else { 02849 cpu_drawV += endTime - startTime; // TIMING 02850 } 02851 #endif 02852 02853 // Next position 02854 pos0 = pos1; 02855 ori0 = ori1; 02856 } 02857 //*/ 02858 } 02859 02860 02861 // Generate cylinder vextex data 02862 template <typename T> 02863 void ModelElasticRod<T>::GenAndDrawCylinderVertexData_SUBDIVISION_Gen ( 02864 unsigned int level, 02865 Vector3<T> posKept[], 02866 Matrix4x4<T> rotMatKept[], 02867 Vector3<T> posPts[], 02868 Matrix4x4<T> rotMatPts[] 02869 ) 02870 { 02871 if ( level < 2 ) return; // this fn only for level >= 2 02872 02873 int idxk = level - 1; // index to kept positions 02874 int size = 2 << (level-1); 02875 int idx0 = size - 2; // I/P index 02876 size = size << 1; 02877 int idx1 = size - 2; // O/P index 02878 GenAndDrawCylinderVertexData_SUBDIVISION_Chaikin_Pts( posKept[idxk], rotMatKept[idxk], posPts[idx0], rotMatPts[idx0], posPts[idx1], rotMatPts[idx1], posPts[idx1+1], rotMatPts[idx1+1] ); 02879 for ( int i = 1; i < size; ++i ) { 02880 ++idx0; 02881 idx1 += 2; 02882 GenAndDrawCylinderVertexData_SUBDIVISION_Chaikin_Pts( posPts[idx0], rotMatPts[idx0], posPts[idx0+1], rotMatPts[idx0+1], posPts[idx1], rotMatPts[idx1], posPts[idx1+1], rotMatPts[idx1+1] ); 02883 } 02884 } 02885 02886 02887 // Draw cylinder vextex data 02888 template <typename T> 02889 void ModelElasticRod<T>::GenAndDrawCylinderVertexData_SUBDIVISION_Draw ( 02890 Vector3<T> const & P, 02891 Matrix4x4<T> const & RotMatP, 02892 Vector3<T> const & Q, 02893 Matrix4x4<T> const & RotMatQ, 02894 T texXstart, 02895 T texXend 02896 ) 02897 { 02898 // Compute the cross section vertices, normals, and texture coordinates for point P 02899 //#pragma omp parallel for 02900 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02901 texCoords[0][i].SetXYZ( texXstart, m_drawCrossSectionTexCoords[i], 0.0 ); 02902 normals[0][i] = Matrix4x4MultVector3( RotMatP, m_drawCrossSectionNormals[i] ); 02903 vertices[0][i] = Matrix4x4MultVector3( RotMatP, sVertices[i] ) + P; 02904 } 02905 // Compute the cross section vertices, normals, and texture coordinates for point Q 02906 //#pragma omp parallel for 02907 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02908 texCoords[2][i].SetXYZ( texXend, m_drawCrossSectionTexCoords[i], 0.0 ); 02909 normals[2][i] = Matrix4x4MultVector3( RotMatQ, m_drawCrossSectionNormals[i] ); 02910 vertices[2][i] = Matrix4x4MultVector3( RotMatQ, sVertices[i] ) + Q; 02911 } 02912 02913 // Draw triangle strip from P to Q 02914 glBegin( GL_TRIANGLE_STRIP ); 02915 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 02916 glTexCoord3fv( texCoords[2][i].GetDataFloat() ); 02917 glNormal3fv( normals[2][i].GetDataFloat() ); 02918 glVertex3fv( vertices[2][i].GetDataFloat() ); 02919 glTexCoord3fv( texCoords[0][i].GetDataFloat() ); 02920 glNormal3fv( normals[0][i].GetDataFloat() ); 02921 glVertex3fv( vertices[0][i].GetDataFloat() ); 02922 } 02923 glTexCoord3fv( texCoords[2][0].GetDataFloat() ); 02924 glNormal3fv( normals[2][0].GetDataFloat() ); 02925 glVertex3fv( vertices[2][0].GetDataFloat() ); 02926 glTexCoord3fv( texCoords[0][0].GetDataFloat() ); 02927 glNormal3fv( normals[0][0].GetDataFloat() ); 02928 glVertex3fv( vertices[0][0].GetDataFloat() ); 02929 glEnd(); 02930 } 02931 02932 02933 // Chaikin's subdivision 02934 template <typename T> 02935 void ModelElasticRod<T>::GenAndDrawCylinderVertexData_SUBDIVISION_Chaikin_Pts ( 02936 Vector3<T> const & Pi, 02937 Matrix4x4<T> const & RotMatPi, 02938 Vector3<T> const & Pj, 02939 Matrix4x4<T> const & RotMatPj, 02940 Vector3<T> & Q, 02941 Matrix4x4<T> & RotMatQ, 02942 Vector3<T> & R, 02943 Matrix4x4<T> & RotMatR 02944 ) 02945 { 02946 Q = 0.75*Pi + 0.25*Pj; 02947 R = 0.25*Pi + 0.75*Pj; 02948 RotMatQ = 0.75*RotMatPi + 0.25*RotMatPj; 02949 RotMatR = 0.25*RotMatPi + 0.75*RotMatPj; 02950 } 02951 02952 //----------------------------------------------------------------------------- 02953 #endif//TAPs_ER_DRAW_WITH_SUBDIVISION 02954 //----------------------------------------------------------------------------- 02955 02956 02957 // Initialize GLSL 02958 template <typename T> 02959 bool ModelElasticRod<T>::InitGLSL () 02960 { 02961 //if ( g_IsGLSLInit ) return true; 02962 02963 if ( Rendering.GetVersionMajorNumber() < 2 ) { 02964 return false; 02965 } 02966 02967 #ifdef TAPs_USE_WXWIDGETS 02968 //std::string texFile( Rendering.GetTAPsResourcePath() + "Textures/Common/four.jpg" ); 02969 std::string texFile( Rendering.GetTAPsResourcePath() + "Textures/Common/Default.jpg" ); 02970 //std::string texFile( Rendering.GetTAPsResourcePath() + "Textures/ForModels/rope_01.jpg" ); 02971 //std::string texFile( Rendering.GetTAPsResourcePath() + "Textures/ForModels/big_brick_01.jpg" ); 02972 if ( Rendering.InitTexture2D( texFile ) ) { 02973 std::cout << "Rendering Info: \n" << Rendering << "\n"; 02974 //return Rendering.InitShaders( "GLSL_ModelElasticRod_wTextures", true, false, true ); 02975 //g_IsGLSLInit = true; 02976 return Rendering.InitShaders( "GLSL_ModelElasticRod_wTextures", true, false, true ); 02977 } 02978 else 02979 #endif//TAPs_USE_WXWIDGETS 02980 { 02981 std::cout << "Rendering Info: \n" << Rendering << "\n"; 02982 //g_IsGLSLInit = true; 02983 return Rendering.InitShaders( "GLSL_ModelElasticRod", true, false, true ); 02984 } 02985 } 02986 #endif//TAPs_USE_GLSL 02987 02988 02989 // Multiplication of Matrix4x4 with Vector3 02990 template <typename T> 02991 Vector3<T> ModelElasticRod<T>::Matrix4x4MultVector3 ( Matrix4x4<T> const &M, Vector3<T> const &V ) const 02992 { 02993 return Vector3<T>( 02994 V[0]*M(0,0) + V[1]*M(0,1) + V[2]*M(0,2) + M(0,3), 02995 V[0]*M(1,0) + V[1]*M(1,1) + V[2]*M(1,2) + M(1,3), 02996 V[0]*M(2,0) + V[1]*M(2,1) + V[2]*M(2,2) + M(2,3) 02997 ); 02998 } 02999 03000 03001 // Compute the vertices and normals of circle corsss section 03002 template <typename T> 03003 void ModelElasticRod<T>::ComputeVerticesAndNormalsOfCircleCrossSection () 03004 { 03005 T stepAngle = 2*Math<T>::PI / m_drawNV; 03006 T angle = 0; 03007 for ( unsigned int i = 0; i < m_drawNV; ++i ) { 03008 T c = cos(angle); 03009 T s = sin(angle); 03010 m_drawCrossSectionVertices[i].SetXYZ( c, s, 0 ); 03011 m_drawCrossSectionNormals[i] = m_drawCrossSectionVertices[i].GetUnit(); 03012 03013 // The first texture coordinate is set to zero and the last one is set to close to or equal to one. 03014 if ( m_drawCrossSectionVertices[i][1] >= 0 ) { 03015 if ( m_drawCrossSectionVertices[i][0] > 0 ) { // the first quadrand 03016 m_drawCrossSectionTexCoords[i] = m_drawCrossSectionVertices[i][1]/4; 03017 } 03018 else { // the second quadrand 03019 m_drawCrossSectionTexCoords[i] = 0.5 - m_drawCrossSectionVertices[i][1]/4; 03020 } 03021 } 03022 else { 03023 if ( m_drawCrossSectionVertices[i][0] < 0 ) { // the third quadrand 03024 m_drawCrossSectionTexCoords[i] = 0.5 - m_drawCrossSectionVertices[i][1]/4; 03025 } 03026 else { // the fourth quadrand 03027 m_drawCrossSectionTexCoords[i] = 1.0 + m_drawCrossSectionVertices[i][1]/4; 03028 } 03029 } 03030 angle += stepAngle; 03031 //std::cout << "m_drawCrossSectionVertices["<<i<<"]: " << m_drawCrossSectionVertices[i] << "\n"; 03032 //std::cout << "m_drawCrossSectionNormals["<<i<<"]: " << m_drawCrossSectionNormals[i] << "\n"; 03033 //std::cout << "m_drawCrossSectionTexCoords["<<i<<"]: " << m_drawCrossSectionTexCoords[i] << "\n"; 03034 } 03035 } 03036 //============================================================================= 03037 #endif // #if defined(__gl_h_) || defined(__GL_H__) 03038 03039 03040 #ifdef TAPs_USE_WXWIDGETS 03041 //============================================================================= 03042 template <typename T> 03043 void ModelElasticRod<T>::ShowPropertyDialog ( wxWindow * parent ) 03044 { 03045 if ( Dialogs.IsInitialized() ) { 03046 // If the dialog is shown, then close it. 03047 if ( Dialogs.IsShown() ) { 03048 Dialogs.Close(); 03049 } 03050 // If the dialog is not shown, then show it. 03051 else { 03052 Dialogs.PropertyDialog<T>( 03053 parent, &m_Parameters, &m_Nodes 03054 #ifdef TAPs_USE_CUDA 03055 , m_CUDA.IsUtilizingPageLockedHostMemory() 03056 #endif//TAPs_USE_CUDA 03057 ); 03058 } 03059 } 03060 else { 03061 wxMessageDialog( NULL, "Elastic Rod's Property Dialog is not available!", "Info", wxOK ); 03062 } 03063 } 03064 //============================================================================= 03065 #endif//TAPs_USE_WXWIDGETS 03066 03067 //============================================================================= 03068 END_NAMESPACE_TAPs 03069 //----------------------------------------------------------------------------- 03070 //34567890123456789012345678901234567890123456789012345678901234567890123456789 03071 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----