TAPs 0.7.7.3
TAPsModelElasticRod.cpp
Go to the documentation of this file.
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----+----
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines