TAPs 0.7.7.3
TAPsCloth.hpp
Go to the documentation of this file.
00001 /******************************************************************************
00002 TAPsCloth.hpp
00003 
00004 Cloth class is a class for a cloth modeled by a network of springs.
00005 
00006 SUKITTI PUNAK   (09/16/2004)
00007 UPDATE          (05/30/2008)
00008 *******************************************************************************
00009 +====================+
00010 | DESCRIPTION / NOTE |
00011 +====================+
00012 
00013 Adapted from "Provot, X. "Deformation Constraints in a Mass-Spring Model to 
00014 Describe Rigid Cloth Behavior," Proc. Graphics Interface, 1995, pp. 147-154."
00015 
00016 The model is a mesh of m-by-n virtual masses, which each mass linked to 
00017 its neighbors by massless springs of natural length greater than zeroes.
00018 The linkage between neighbors comprised of three kinds of linking springs:
00019   -- Structural springs linking masses [m,n] and [m+1,n], and 
00020                                 masses [m,n] and [m,n+1]
00021   -- Shear springs linking masses [m,n] and [m+1,n+1], and 
00022                            masses [m+1,n] and [m,n+1]
00023   -- Flexion springs linking masses [m,n] and [m+2,n], and 
00024                              masses [m,n] and [m,n+2]
00025 
00026   (0,0)---------(0,1)---------(0,2)
00027     |  \       /  |  \       /  |
00028     |    \   /    |    \   /    |
00029     |      +      |      +      |
00030     |    /   \    |    /   \    |
00031     |  /       \  |  /       \  |
00032   (1,0)---------(1,1)---------(1,2)
00033     |  \       /  |  \       /  |
00034     |    \   /    |    \   /    |
00035     |      +      |      +      |
00036     |    /   \    |    /   \    |
00037     |  /       \  |  /       \  |
00038   (2,0)---------(2,1)---------(2,2)
00039 
00040 ******************************************************************************/
00041 #ifndef TAPs_CLOTH_HPP
00042 #define TAPs_CLOTH_HPP
00043 
00044 #include "../Physics/TAPsPhysics.hpp"   // for gravitational constant
00045 #include "../Physics/TAPsSpring.hpp"    // SPT_Spring.h all ready include SPT_Particle.h
00046 #include "../OpenGL/TAPsOpenGLSupport.hpp"
00047 
00048 BEGIN_NAMESPACE_TAPs
00049 //=============================================================================
00050 template <typename T>
00051 class Cloth : public /*virtual*/ OpenGL::OpenGLSupport {
00052 //=============================================================================
00053     //-------------------------------------------------------------------------
00054     // put it through ostream
00055     friend std::ostream &operator<<( std::ostream &output, const Cloth<T> &Obj )
00056     {
00057         output  << "Cloth ==> "
00058                 << "\n  number of rows:       " << Obj.m_iNoRows
00059                 << "\n  number of columns:    " << Obj.m_iNoCols
00060                 << "\n  viscous damping:      " << Obj.m_tKvd
00061                 << "\n  wind damping:         " << Obj.m_tKvfm
00062                 << "\n  stiffness of structural, shear, and flexion springs: " 
00063                         << Obj.m_tKs[0] << ", " << Obj.m_tKs[1] << ", and " << Obj.m_tKs[2]
00064                 << "\n  damping constant for structural, shear, and flexion springs: "
00065                         << Obj.m_tKd[0] << ", " << Obj.m_tKd[1] << ", and " << Obj.m_tKd[2]
00066                 << "\n  length constrain for structural, shear, and flextion springs: "
00067                         << Obj.m_tLengthConstrain[0] << ", " 
00068                         << Obj.m_tLengthConstrain[1] << ", and " 
00069                         << Obj.m_tLengthConstrain[2]
00070                 << "\n";
00071 
00072         return output;
00073     }
00074 
00075 //-------------------------------------------------------------------------------------------------
00076 private:
00077     // Data Members     ============================================================================
00078     int m_iNoRows;  // number of rows in y-direction    (y values) (normally called weft)
00079     int m_iNoCols;  // number of columns in x-direction (x values) (normally called warp)
00080     T   m_tKvd;             // viscous damping of cloth
00081     T   m_tKvfm;            // viscous fluid moving damping of cloth
00082     T   m_tKs[3];           // stiffness spring constant for structural, shear, and flexion springs
00083     T   m_tKd[3];           // damping constant for structural, shear, and flexion springs
00084     T   m_tLengthConstrain[3];  // Length Constrain for structural, shear, and flexion springs
00085 
00086     // Mass Points
00087     Particle<T> ***m_pcParticle;
00088     // Linking Springs
00089     Spring<T> ***m_pcSpringStructuralRow;   // (structural, stretching, or tensile) springs linking masses [m,n] and [m,n+1]
00090     Spring<T> ***m_pcSpringStructuralCol;   // (structural, stretching, or tensile) springs linking masses [m,n] and [m+1,n]
00091     Spring<T> ***m_pcSpringShearTLtoBR;     // (shear) springs linking masses [m,n] and [m+1,n+1]
00092     Spring<T> ***m_pcSpringShearBLtoTR;     // (shear) springs linking masses [m+1,n] and [m,n+1]
00093     Spring<T> ***m_pcSpringFlexionRow;      // (flexion or bending) springs linking masses [m,n] and [m,n+2]
00094     Spring<T> ***m_pcSpringFlexionCol;      // (flexion or bending) springs linking masses [m,n] and [m+2,n]
00095 
00096     // object counters
00097     int m, n;   // m = row number; n = col number
00098 //-------------------------------------------------------------------------------------------------
00099 private:
00100     // Helper Functions     ========================================================================
00101     void CreateParticles( Vector3<T> const &topLeftPos, Vector3<T> const &bottomRightPos, T mass );
00102     void DeleteParticles();
00103     void CreateSprings();
00104     void DeleteSprings();
00105     void AddSpringForces();     // calculate and add spring forces to particle forces
00106                                 // This fn calls AddSpringForce(.) fn.
00107     inline void AddSpringForce( Spring<T> * const sp ); // calculate and add the force of a spring
00108 
00109     // Limit Lengths of Springs
00110     void LimitSpringLengths();  // limit the lengths of all springs
00111                                 // This fn calls LimitSpringLength(.) fn.
00112     inline void LimitSpringLength( Spring<T> * const sp, T lengthLimit );
00113 
00114     //void BindingTexture
00115 //-------------------------------------------------------------------------------------------------
00116 public:
00117     // Member Functions     ========================================================================
00118     // Constructor -------------------------------------------------------------
00119     Cloth( int rows,            // number of rows (on world-y-axis)
00120               int cols,         // number of rows (on world-x-axis)
00121               T Kvd,                    // viscous damping constant
00122               T Kvfm,                   // viscous fluid moving constant
00123               T Ks,                             // spring stiffness constant
00124               T Kd,                             // spring damping constant
00125               T lengthConstrain,                // spring rest length
00126               const Vector3<T> &topLeftPos,         // start position (should be top left cornor)
00127               const Vector3<T> &bottomRightPos,     // end position (should be bottom right cornor)
00128               T mass,                                   // the whole mass
00129               BitmapImage * = NULL );       // Image Pointer
00130     // Constructor -------------------------------------------------------------
00131     Cloth( int rows,            // number of rows (on world-y-axis)
00132               int cols,         // number of rows (on world-x-axis)
00133               T Kvd,                    // viscous damping constant
00134               T Kvfm,                   // viscous fluid moving constant
00135               T Ks0,                            // structural spring stiffness constant
00136               T Ks1,                            // shear      spring stiffness constant
00137               T Ks2,                            // flexion    spring stiffness constant
00138               T Kd0,                            // structural spring damping constant
00139               T Kd1,                            // shear      spring damping constant
00140               T Kd2,                            // flexion    spring damping constant
00141               T lengthConstrain0,               // structural spring rest length
00142               T lengthConstrain1,               // shear      spring rest length
00143               T lengthConstrain2,               // flexion    spring rest length
00144               const Vector3<T> &topLeftPos,         // start position (should be top left cornor)
00145               const Vector3<T> &bottomRightPos,     // end position (should be bottom right cornor)
00146               T mass,                                   // the whole mass
00147               BitmapImage * = NULL );       // Image Pointer
00148     //-------------------------------------------------------------------------
00149     ~Cloth();                           // destructor
00150     //-------------------------------------------------------------------------
00151     // CalParticleNormals( int i ) should runs faster than CalParticleNormals(),
00152     // since it calculates the normals more direct.
00153     void CalParticleNormals();          // calculate particle normals
00154     void CalParticleNormals( int i );   // calculate particle normals, int i is dummy
00155     void AddNormal( Vector3<T> & Dest, 
00156                     Vector3<T> const & A, Vector3<T> const & B, Vector3<T> const & C );
00157 
00158 
00159     // Calculate Forces --------------------------------------------------------
00160     /*
00161     void ClearForce();                      // clear force of particles to zeros
00162     void ForceDueToGravity( T g = SP_Physics::g );  // calculate (weight) force due to (acceleration of) gravity
00163     void ForceDueToViscousDamping();        // calculate (a loss) force due to viscous damping
00164     void ForceDueToViscousFluidMoving();    // calculate (wind)   force due to viscous fluid moving
00165     */
00166     // Calculate All Forces Acting on Particles
00167     void CalForces( Vector3<T> vWind = Vector3<T>(0,0,0), T g = Physics_SI::K::g );
00168 
00169     // Display Routine(s) ------------------------------------------------------
00170     void DisplayGL( OpenGL::Enum::DrawMode DM = OpenGL::Enum::POLYGON );        // display cloth
00171     void DisplayGL_ParticleNormals();                       // display particle normals
00172 protected:
00173     //-------------------------------------------------------------------------
00174     // Override a pure Virtual fn inherited from OpenGLSupport class
00175     // Helper Fn
00176     // void DrawGL()
00177     virtual void DrawGL ( GLenum ) {};
00178     //-------------------------------------------------------------------------
00179 public:
00180     // Get/Set Functions
00181     bool GetParticleFixStatus( int r, int c ) const     { return m_pcParticle[r][c]->m_bFixed; }
00182     void SetParticleFixStatus( int r, int c, bool b )   { m_pcParticle[r][c]->m_bFixed = b; }
00183 
00184     // TEST
00185     void StepSimulation( T dt ) {
00186         T divider = 10.0;
00187         CalForces( Vector3<T>( (rand()%1000)/divider, (rand()%10)/divider, (rand()%10)/divider ) );
00188         //CalForces();
00189         // Euler's Method for Integration for ODE Solver
00190         for ( m = 0; m < m_iNoRows; m++ ) {
00191             for ( n = 0; n < m_iNoCols; n++ ) {
00192                 m_pcParticle[m][n]->m_vtAccel  = m_pcParticle[m][n]->m_vtForce / m_pcParticle[m][n]->m_tMass;
00193                 m_pcParticle[m][n]->m_vtVeloc += m_pcParticle[m][n]->m_vtAccel * dt;
00194                 m_pcParticle[m][n]->m_vtPosit += m_pcParticle[m][n]->m_vtVeloc * dt;
00195             }
00196         }
00197         LimitSpringLengths();
00198     }
00199 };
00200 //CLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLASSCLA
00201 
00202 
00203 //HELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHE
00204 //
00205 //      Cloth   H E L P E R    F U N C T I O N    M E M B E R    D E F I N I T I O N S
00206 //
00207 //HELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHE
00208 //-------------------------------------------------------------------------------------------------
00209 // Create Particles
00210 template <typename T>
00211 void Cloth<T>::CreateParticles( const Vector3<T> &topLeftPos, const Vector3<T> &bottomRightPos, T mass )
00212 {
00213     // Local Variable
00214     Vector3<T> currentPosVector = topLeftPos;
00215     Vector3<T> diagonalVector = bottomRightPos - topLeftPos;
00216     T ptMass = mass / ( m_iNoCols * m_iNoRows );
00217     T colIncStep = diagonalVector[0] / (m_iNoCols-1);
00218     T rowIncStep = diagonalVector[1] / (m_iNoRows-1);
00219     //T zIncStep   = diagonalVector[2] / ((m_iNoCols + m_iNoRows)/2.0);
00220     T zIncStep   = diagonalVector[2] / (m_iNoRows-1);
00221 
00222     // Create Particle Pointers
00223     m_pcParticle = new Particle<T>**[m_iNoRows];
00224     for ( m = 0; m < m_iNoRows; m++ ) {
00225         m_pcParticle[m] = new Particle<T>*[m_iNoCols];
00226     }
00227 
00228     // Create Particles
00229     Vector3<T> zeroVector(0,0,0);
00230     for ( m = 0; m < m_iNoRows; m++ ) { // row loops
00231         for ( n = 0; n < m_iNoCols; n++ ) { // column loops
00232             m_pcParticle[m][n] = new Particle<T>( ptMass,   // mass 
00233                                      currentPosVector,  // position
00234                                      zeroVector,        // velocity
00235                                      zeroVector,        // acceleration
00236                                      zeroVector );      // force
00237             currentPosVector[0] = currentPosVector[0] + colIncStep; // increment x position
00238         }
00239         currentPosVector[0] = topLeftPos[0];                    // reset x position
00240         currentPosVector[1] = currentPosVector[1] + rowIncStep; // increment y position
00241         currentPosVector[2] = currentPosVector[2] + zIncStep;   // increment z position
00242     }
00243 
00244     #ifdef  TAPs_DEBUG_MODE
00245     // Dump Particle Positions on Screen
00246     for ( m = 0; m < m_iNoRows; m++ ) { // row loops
00247         for ( n = 0; n < m_iNoCols; n++ ) { // column loops
00248             std::cout << "[" << m << "," << n << "] " << m_pcParticle[m][n]->m_vtPosit << " ";
00249         }
00250         std::cout << "\n";
00251     }
00252     #endif//TAPs_DEBUG_MODE
00253 }
00254 //-------------------------------------------------------------------------------------------------
00255 // Delete Particles
00256 template <typename T>
00257 void Cloth<T>::DeleteParticles()
00258 {
00259     // Delete Particles
00260     for ( m = 0; m < m_iNoRows; m++ ) {
00261         for ( n = 0; n < m_iNoCols; n++ ) {
00262             delete m_pcParticle[m][n];
00263         }
00264         delete [] m_pcParticle[m];
00265     }
00266     delete [] m_pcParticle;
00267 }
00268 //-------------------------------------------------------------------------------------------------
00269 // Create Springs
00270 template <typename T>
00271 void Cloth<T>::CreateSprings()
00272 {
00273     // ========== CREATE SPRING POINTERS =======================================
00274     // Create Structural Spring Pointers ---------------------------------------
00275     m_pcSpringStructuralRow = new Spring<T>**[m_iNoRows];           // Row [m,n] and [m,n+1]
00276     for ( m = 0; m < m_iNoRows; m++ ) {
00277         m_pcSpringStructuralRow[m] = new Spring<T>*[m_iNoCols-1];
00278     }
00279     m_pcSpringStructuralCol = new Spring<T>**[m_iNoCols];           // Col [m,n] and [m+1,n]
00280     for ( n = 0; n < m_iNoCols; n++ ) {
00281         m_pcSpringStructuralCol[n] = new Spring<T>*[m_iNoRows-1];
00282     }
00283     // Create Shear Spring Pointers --------------------------------------------
00284     m_pcSpringShearTLtoBR = new Spring<T>**[m_iNoRows-1];           // [m,n] and [m+1,n+1]
00285     m_pcSpringShearBLtoTR = new Spring<T>**[m_iNoRows-1];           // [m+1,n] and [m,n+1]
00286     for ( m = 0; m < m_iNoRows-1; m++ ) {
00287         m_pcSpringShearTLtoBR[m] = new Spring<T>*[m_iNoCols-1];
00288         m_pcSpringShearBLtoTR[m] = new Spring<T>*[m_iNoCols-1];
00289     }
00290     // Create Flexion Spring Pointers ------------------------------------------
00291     m_pcSpringFlexionRow = new Spring<T>**[m_iNoRows];          // Row [m,n] and [m,n+2]
00292     for ( m = 0; m < m_iNoRows; m++ ) {
00293         m_pcSpringFlexionRow[m] = new Spring<T>*[m_iNoCols-2];
00294     }
00295     m_pcSpringFlexionCol = new Spring<T>**[m_iNoCols];          // Col [m,n] and [m+2,n]
00296     for ( n = 0; n < m_iNoCols; n++ ) {
00297         m_pcSpringFlexionCol[n] = new Spring<T>*[m_iNoRows-2];
00298     }
00299 
00300     // ========== CREATE SPRING ================================================
00301     // Create Structural Springs -----------------------------------------------
00302     // Row [m,n] and [m,n+1]
00303     int id = 0;     // 0 for structural spring
00304 
00305     #ifdef  TAPs_DEBUG_MODE
00306     // Dump
00307     std::cout << "Spring Length of Row [m,n] and [m,n+1]\n";
00308     #endif//TAPs_DEBUG_MODE
00309 
00310     for ( m = 0; m < m_iNoRows; m++ ) {
00311         for ( n = 0; n < m_iNoCols-1; n++ ) {
00312             m_pcSpringStructuralRow[m][n] = new Spring<T>( 
00313                     *m_pcParticle[m][n], *m_pcParticle[m][n+1], // linked points
00314                     m_tKs[id], m_tKd[id],                       // stiffness and damping const
00315                     (   m_pcParticle[m][n]->m_vtPosit 
00316                       - m_pcParticle[m][n+1]->m_vtPosit).Length()   // spring length
00317                 );
00318 
00319             #ifdef  TAPs_DEBUG_MODE
00320             // Dump (cont.)
00321             std::cout << "  " << m_pcSpringStructuralRow[m][n]->GetRestLengthL();
00322             #endif//TAPs_DEBUG_MODE
00323         }
00324 
00325         #ifdef  TAPs_DEBUG_MODE
00326         // Dump (cont.)
00327         std::cout << "\n";
00328         #endif//TAPs_DEBUG_MODE
00329     }
00330     // Col [m,n] and [m+1,n]
00331 
00332     #ifdef  TAPs_DEBUG_MODE
00333     // Dump
00334     std::cout << "Spring Length of Col [m,n] and [m+1,n]\n";
00335     #endif//TAPs_DEBUG_MODE
00336 
00337     for ( n = 0; n < m_iNoCols; n++ ) {
00338         for ( m = 0; m < m_iNoRows-1; m++ ) {
00339             m_pcSpringStructuralCol[n][m] = new Spring<T>( 
00340                     *m_pcParticle[m][n], *m_pcParticle[m+1][n],     // linked points
00341                     m_tKs[id], m_tKd[id],                           // stiffness and damping const
00342                     (   m_pcParticle[m][n]->m_vtPosit 
00343                       - m_pcParticle[m+1][n]->m_vtPosit).Length()   // spring length
00344                 );
00345 
00346             #ifdef  TAPs_DEBUG_MODE
00347             // Dump (cont.)
00348             std::cout << "  " << m_pcSpringStructuralCol[n][m]->GetRestLengthL();
00349             #endif//TAPs_DEBUG_MODE
00350         }
00351 
00352         #ifdef  TAPs_DEBUG_MODE
00353         // Dump (cont.)
00354         std::cout << "\n";
00355         #endif//TAPs_DEBUG_MODE
00356     }
00357     // Create Shear Springs ----------------------------------------------------
00358     id = 1;     // 1 for shear spring
00359 
00360     #ifdef  TAPs_DEBUG_MODE
00361     // Dump
00362     std::cout << "Spring Length of [m,n] and [m+1,n+1] and ";
00363     std::cout << "Spring Length of [m+1,n] and [m,n+1]\n";
00364     #endif//TAPs_DEBUG_MODE
00365 
00366     int mm, nn;
00367     for ( m = 0, mm = 1; m < m_iNoRows-1; m++, mm++ ) {
00368         for ( n = 0, nn = 1; n < m_iNoCols-1; n++, nn++ ) {
00369             m_pcSpringShearTLtoBR[m][n] = new Spring<T>( 
00370                     *m_pcParticle[m][n], *m_pcParticle[mm][nn],     // linked points
00371                     m_tKs[id], m_tKd[id],                           // stiffness and damping const
00372                     (   m_pcParticle[m][n]->m_vtPosit 
00373                       - m_pcParticle[mm][nn]->m_vtPosit).Length()   // spring length
00374                 );
00375             m_pcSpringShearBLtoTR[m][n] = new Spring<T>( 
00376                     *m_pcParticle[mm][n], *m_pcParticle[m][nn],     // linked points
00377                     m_tKs[id], m_tKd[id],                           // stiffness and damping const
00378                     (   m_pcParticle[mm][n]->m_vtPosit 
00379                       - m_pcParticle[m][nn]->m_vtPosit).Length()    // spring length
00380                 );
00381 
00382             #ifdef  TAPs_DEBUG_MODE
00383             // Dump (cont.)
00384             std::cout << "  (" << m_pcSpringShearTLtoBR[m][n]->GetRestLengthL();
00385             // Dump (cont.)
00386             std::cout << ", " << m_pcSpringShearBLtoTR[m][n]->GetRestLengthL() << ")  ";
00387             #endif//TAPs_DEBUG_MODE
00388         }
00389 
00390         #ifdef  TAPs_DEBUG_MODE
00391         // Dump (cont.)
00392         std::cout << "\n";
00393         #endif//TAPs_DEBUG_MODE
00394     }
00395     // Create Flexion Springs --------------------------------------------------
00396     id = 2;     // 2 for flexion spring
00397     // Row [m,n] and [m,n+2]
00398 
00399     #ifdef  TAPs_DEBUG_MODE
00400     // Dump
00401     std::cout << "Spring Length of Row [m,n] and [m,n+2]\n";
00402     #endif//TAPs_DEBUG_MODE
00403 
00404     for ( m = 0; m < m_iNoRows; m++ ) {
00405         for ( n = 0; n < m_iNoCols-2; n++ ) {
00406             m_pcSpringFlexionRow[m][n] = new Spring<T>( 
00407                     *m_pcParticle[m][n], *m_pcParticle[m][n+2], // linked points
00408                     m_tKs[id], m_tKd[id],                       // stiffness and damping const
00409                     (   m_pcParticle[m][n]->m_vtPosit 
00410                       - m_pcParticle[m][n+2]->m_vtPosit).Length()   // spring length
00411                 );
00412 
00413             #ifdef  TAPs_DEBUG_MODE
00414             // Dump (cont.)
00415             std::cout << "  " << m_pcSpringFlexionRow[m][n]->GetRestLengthL();
00416             #endif//TAPs_DEBUG_MODE
00417         }
00418 
00419         #ifdef  TAPs_DEBUG_MODE
00420         // Dump (cont.)
00421         std::cout << "\n";
00422         #endif//TAPs_DEBUG_MODE
00423     }
00424     // Col [m,n] and [m+2,n]
00425 
00426     #ifdef  TAPs_DEBUG_MODE
00427     // Dump
00428     std::cout << "Spring Length of Col [m,n] and [m+2,n]\n";
00429     #endif//TAPs_DEBUG_MODE
00430 
00431     for ( n = 0; n < m_iNoCols; n++ ) {
00432         for ( m = 0; m < m_iNoRows-2; m++ ) {
00433             m_pcSpringFlexionCol[n][m] = new Spring<T>( 
00434                     *m_pcParticle[m][n], *m_pcParticle[m+2][n],     // linked points
00435                     m_tKs[id], m_tKd[id],                           // stiffness and damping const
00436                     (   m_pcParticle[m][n]->m_vtPosit 
00437                       - m_pcParticle[m+2][n]->m_vtPosit).Length()   // spring length
00438                 );
00439 
00440             #ifdef  TAPs_DEBUG_MODE
00441             // Dump (cont.)
00442             std::cout << "  " << m_pcSpringFlexionCol[n][m]->GetRestLengthL();
00443             #endif//TAPs_DEBUG_MODE
00444         }
00445 
00446         #ifdef  TAPs_DEBUG_MODE
00447         // Dump (cont.)
00448         std::cout << "\n";
00449         #endif//TAPs_DEBUG_MODE
00450     }
00451 }
00452 //-------------------------------------------------------------------------------------------------
00453 // Delete Springs
00454 template <typename T>
00455 void Cloth<T>::DeleteSprings()
00456 {
00457     // Delete Structural Springs -----------------------------------------------
00458     // Row [m,n] and [m,n+1]
00459     for ( m = 0; m < m_iNoRows; m++ ) {
00460         for ( n = 0; n < m_iNoCols-1; n++ ) {
00461             delete m_pcSpringStructuralRow[m][n];
00462         }
00463         delete [] m_pcSpringStructuralRow[m];
00464     }
00465     delete [] m_pcSpringStructuralRow;
00466     // Col [m,n] and [m+1,n]
00467     for ( n = 0; n < m_iNoCols; n++ ) {
00468         for ( m = 0; m < m_iNoRows-1; m++ ) {
00469             delete m_pcSpringStructuralCol[n][m];
00470         }
00471         delete [] m_pcSpringStructuralCol[n];
00472     }
00473     delete [] m_pcSpringStructuralCol;
00474     // Delete Shear Springs ----------------------------------------------------
00475     // [m,n] and [m+1,n+1]
00476     // [m+1,n] and [m,n+1]
00477     for ( m = 0; m < m_iNoRows-1; m++ ) {
00478         for ( n = 0; n < m_iNoCols-1; n++ ) {
00479             delete m_pcSpringShearTLtoBR[m][n];
00480             delete m_pcSpringShearBLtoTR[m][n];
00481         }
00482         delete [] m_pcSpringShearTLtoBR[m];
00483         delete [] m_pcSpringShearBLtoTR[m];
00484     }
00485     delete [] m_pcSpringShearTLtoBR;
00486     delete [] m_pcSpringShearBLtoTR;
00487     // Delete Flexion Springs --------------------------------------------------
00488     // Row [m,n] and [m,n+2]
00489     for ( m = 0; m < m_iNoRows; m++ ) {
00490         for ( n = 0; n < m_iNoCols-2; n++ ) {
00491             delete m_pcSpringFlexionRow[m][n];
00492         }
00493         delete [] m_pcSpringFlexionRow[m];
00494     }
00495     delete [] m_pcSpringFlexionRow;
00496     // Col [m,n] and [m+2,n]
00497     for ( n = 0; n < m_iNoCols; n++ ) {
00498         for ( m = 0; m < m_iNoRows-2; m++ ) {
00499             delete m_pcSpringFlexionCol[n][m];
00500         }
00501         delete [] m_pcSpringFlexionCol[n];
00502     }
00503     delete [] m_pcSpringFlexionCol;
00504 }
00505 //-------------------------------------------------------------------------------------------------
00506 // Calculate and Add Spring Forces to Particle Forces
00507 template <typename T>
00508 void Cloth<T>::AddSpringForces()
00509 {
00510     //==========================================================================
00511     // CALCULATE STRUCTURAL SPRING FORCE
00512     // Process on Row Structural Spring
00513     for ( m = 0; m < m_iNoRows; m++ ) {
00514         for ( n = 0; n < m_iNoCols-1; n++ ) {
00515             AddSpringForce( m_pcSpringStructuralRow[m][n] );
00516         }
00517     }
00518     // Process on Column Structural Spring
00519     for ( n = 0; n < m_iNoCols; n++ ) {
00520         for ( m = 0; m < m_iNoRows-1; m++ ) {
00521             AddSpringForce( m_pcSpringStructuralCol[n][m] );
00522         }
00523     }
00524     //==========================================================================
00525     // CALCULATE SHEAR SPRING FORCE
00526     for ( m = 0; m < m_iNoRows-1; m++ ) {
00527         for ( n = 0; n < m_iNoCols-1; n++ ) {
00528             AddSpringForce( m_pcSpringShearTLtoBR[m][n] );
00529             AddSpringForce( m_pcSpringShearBLtoTR[m][n] );
00530         }
00531     }
00532     //==========================================================================
00533     // CALCULATE FLEXION SPRING FORCE
00534     // Process on Row Flexion Spring
00535     for ( m = 0; m < m_iNoRows; m++ ) {
00536         for ( n = 0; n < m_iNoCols-2; n++ ) {
00537             AddSpringForce( m_pcSpringFlexionRow[m][n] );
00538         }
00539     }
00540     // Process on Column Flexion Spring
00541     for ( n = 0; n < m_iNoCols; n++ ) {
00542         for ( m = 0; m < m_iNoRows-2; m++ ) {
00543             AddSpringForce( m_pcSpringFlexionCol[n][m] );
00544         }
00545     }
00546 }
00547 //-------------------------------------------------------------------------------------------------
00548 // Calculate and Add the Force of a Spring
00549 template <typename T>
00550 inline void Cloth<T>::AddSpringForce( Spring<T> * const sp )
00551 {
00552     /*
00553     // Local Variables ---------------------------------------------------------
00554     // spring current length vector
00555     Vector3<T> cL = ( sp->m_rcP1.m_vtPosit - sp->m_rcP2.m_vtPosit );
00556     // spring current length scalar
00557     T scl = cL.Length();
00558     // velocity difference of the two particles linked by the spring
00559     Vector3<T> V = ( sp->m_rcP1.m_vtVeloc - sp->m_rcP2.m_vtVeloc );
00560 
00561     // F1 = -{Ks(l - r) + Kd[(V1-V2)*L]/l}*L/l
00562     // F2 = -F1
00563     //   where Ks = spring stiffness, Kd = spring damping,
00564     //     V1 and V2 are velocity of particles linked by the spring
00565     //     r = spring rest length
00566     //     L = vector of difference of positions of particle#1 and #2
00567     //     l = magnitude of L
00568     Vector3<T> f  = -( (sp->m_tK * (scl - sp->m_tL)) +  (sp->m_tD * ((V*cL) / scl)) ) * (cL / scl);
00569     // Update the particle forces
00570     */
00571     if ( !sp->m_rcP1.m_bFixed ) sp->m_rcP1.m_vtForce += sp->GetForce();
00572     if ( !sp->m_rcP2.m_bFixed ) sp->m_rcP2.m_vtForce -= sp->GetForce();
00573 }
00574 //-------------------------------------------------------------------------------------------------
00575 // Limit the Length of All Springs
00576 template <typename T>
00577 void Cloth<T>::LimitSpringLengths()
00578 {
00579     int d = 0;
00580     //==========================================================================
00581     // CALCULATE STRUCTURAL SPRING FORCE
00582     // Process on Row Structural Spring
00583     for ( m = 0; m < m_iNoRows; m++ ) {
00584         for ( n = 0; n < m_iNoCols-1; n++ ) {
00585             LimitSpringLength( m_pcSpringStructuralRow[m][n], m_tLengthConstrain[d] );
00586         }
00587     }
00588     // Process on Column Structural Spring
00589     for ( n = 0; n < m_iNoCols; n++ ) {
00590         for ( m = 0; m < m_iNoRows-1; m++ ) {
00591             LimitSpringLength( m_pcSpringStructuralCol[n][m], m_tLengthConstrain[d] );
00592         }
00593     }
00594     //==========================================================================
00595     // CALCULATE SHEAR SPRING FORCE
00596     d = 1;
00597     for ( m = 0; m < m_iNoRows-1; m++ ) {
00598         for ( n = 0; n < m_iNoCols-1; n++ ) {
00599             LimitSpringLength( m_pcSpringShearTLtoBR[m][n], m_tLengthConstrain[d] );
00600             LimitSpringLength( m_pcSpringShearBLtoTR[m][n], m_tLengthConstrain[d] );
00601         }
00602     }
00603     //==========================================================================
00604     // CALCULATE FLEXION SPRING FORCE
00605     // Process on Row Flexion Spring
00606     d = 2;
00607     for ( m = 0; m < m_iNoRows; m++ ) {
00608         for ( n = 0; n < m_iNoCols-2; n++ ) {
00609             LimitSpringLength( m_pcSpringFlexionRow[m][n], m_tLengthConstrain[d] );
00610         }
00611     }
00612     // Process on Column Flexion Spring
00613     for ( n = 0; n < m_iNoCols; n++ ) {
00614         for ( m = 0; m < m_iNoRows-2; m++ ) {
00615             LimitSpringLength( m_pcSpringFlexionCol[n][m], m_tLengthConstrain[d] );
00616         }
00617     }
00618 }
00619 //-------------------------------------------------------------------------------------------------
00620 // Limit the Length of All Springs
00621 template <typename T>
00622 inline void Cloth<T>::LimitSpringLength( Spring<T> * const sp, T lengthLimit )
00623 {
00624     Vector3<T> vLength = sp->m_rcP2.m_vtPosit - sp->m_rcP1.m_vtPosit;
00625     T currentLength = vLength.Length();
00626     T restLength    = sp->GetRestLengthL();
00627     T difference    = currentLength - restLength;
00628     // Spring is straighten too high
00629     if      ( difference > lengthLimit ) {
00630         // both particles are not fixed.
00631         if      ( !sp->m_rcP2.m_bFixed && !sp->m_rcP1.m_bFixed ) {
00632             //cout << difference << " = " << currentLength << " - " << restLength << "\n";
00633             vLength *= difference / 20.0;
00634             //vLength *= lengthLimit / 2.0;
00635             sp->m_rcP1.m_vtPosit += vLength;
00636             sp->m_rcP2.m_vtPosit -= vLength;
00637             return;
00638         }
00639         // particle#1 is fixed, while particle#2 is not fixed.
00640         else if ( sp->m_rcP2.m_bFixed && !sp->m_rcP1.m_bFixed ) {
00641             vLength *= difference;
00642             sp->m_rcP1.m_vtPosit += vLength;
00643             return;
00644         }
00645         // particle#1 is not fixed, while particle#2 is fixed.
00646         else if ( !sp->m_rcP2.m_bFixed && sp->m_rcP1.m_bFixed ) {
00647             vLength *= difference;
00648             sp->m_rcP2.m_vtPosit -= vLength;
00649             return;
00650         }
00651     }
00652     // Spring is compressed too high
00653     else if ( difference > -lengthLimit ) {
00654         
00655     }
00656     // Spring length is within the limit
00657     else {
00658     }
00659 }
00660 //HELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHELPERHE
00661 
00662 
00663 //MEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERME
00664 //
00665 //      Cloth   F U N C T I O N    M E M B E R    D E F I N I T I O N S
00666 //
00667 //MEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERME
00668 //-------------------------------------------------------------------------------------------------
00669 template <typename T>
00670 Cloth<T>::Cloth( int rows,  // number of rows (on world-y-axis)
00671               int cols,             // number of cols (on world-x-axis)
00672               T Kvd,                    // viscous damping constant
00673               T Kvfm,                   // viscous fluid moving constant
00674               T Ks,                             // spring stiffness constant
00675               T Kd,                             // spring damping constant
00676               T lengthConstrain,                // spring rest length
00677               const Vector3<T> &topLeftPos,         // start position (should be top left cornor)
00678               const Vector3<T> &bottomRightPos,     // end position (should be bottom right cornor)
00679               T mass,                                   // the whole mass
00680               BitmapImage *img )            // Image Pointer
00681     : OpenGLSupport( img ),     // parent class constructor
00682       m_iNoRows( rows ), m_iNoCols( cols ), m_tKvd( Kvd ), m_tKvfm( Kvfm )
00683 {
00684     m_tKs[0] = m_tKs[1] = m_tKs[2] = Ks;
00685     m_tKd[0] = m_tKd[1] = m_tKd[2] = Kd;
00686     m_tLengthConstrain[0] = m_tLengthConstrain[1] = m_tLengthConstrain[2] = lengthConstrain;
00687     CreateParticles( topLeftPos, bottomRightPos, mass );
00688     CreateSprings();
00689     CalParticleNormals( 0 );
00690     EnableTexture();
00691 }
00692 //-------------------------------------------------------------------------------------------------
00693 template <typename T>
00694 Cloth<T>::Cloth( int rows,  // number of rows (on world-y-axis)
00695               int cols,             // number of cols (on world-x-axis)
00696               T Kvd,                    // viscous damping constant
00697               T Kvfm,                   // viscous fluid moving constant
00698               T Ks0,                            // structural spring stiffness constant
00699               T Ks1,                            // shear      spring stiffness constant
00700               T Ks2,                            // flexion    spring stiffness constant
00701               T Kd0,                            // structural spring damping constant
00702               T Kd1,                            // shear      spring damping constant
00703               T Kd2,                            // flexion    spring damping constant
00704               T lengthConstrain0,               // structural spring rest length
00705               T lengthConstrain1,               // shear      spring rest length
00706               T lengthConstrain2,               // flexion    spring rest length
00707               const Vector3<T> &topLeftPos,         // start position (should be top left cornor)
00708               const Vector3<T> &bottomRightPos,     // end position (should be bottom right cornor)
00709               T mass,                                   // the whole mass
00710               BitmapImage *img )            // Image Pointer
00711     : OpenGLSupport( img ),     // parent class constructor
00712       m_iNoRows( rows ), m_iNoCols( cols ), m_tKvd( Kvd ), m_tKvfm( Kvfm )
00713 {
00714     m_tKs[0] = Ks0;    m_tKs[1] = Ks1;    m_tKs[2] = Ks2;
00715     m_tKd[0] = Kd0;    m_tKd[1] = Kd1;    m_tKd[2] = Kd2;
00716     m_tLengthConstrain[0] = lengthConstrain0;
00717     m_tLengthConstrain[1] = lengthConstrain1;
00718     m_tLengthConstrain[2] = lengthConstrain2;
00719     CreateParticles( topLeftPos, bottomRightPos, mass );
00720     CreateSprings();
00721     CalParticleNormals( 0 );
00722 }
00723 //-------------------------------------------------------------------------------------------------
00724 template <typename T>
00725 Cloth<T>::~Cloth()
00726 {
00727     DeleteParticles();
00728     DeleteSprings();
00729 }
00730 //-------------------------------------------------------------------------------------------------
00731 // Calculate Particle Normals
00732 template <typename T>
00733 void Cloth<T>::CalParticleNormals()
00734 {
00735 /*
00736     -----------------
00737     | \  3  |  2  / |
00738     |   \   |   /   |
00739     | 4   \ | /  1  |   Normal of the middle (m,n) particle is the sum of the eight normals.
00740     |<------+------>|   E.g. normal 1 is the unit vector of the cross product of (m,n)-->(m,n+1) 
00741     | 5   / | \  8  |   vector with (m,n)-->(m-1,n+1) vector (rotated counter clockwise).
00742     |   /   |   \   |
00743     | /  6  |  7  \ |
00744     -----------------
00745 */
00746     // These particles have all 8 neighbors ------------------------------------
00747     for ( m = 1; m < m_iNoRows-1; m++ ) {
00748         for ( n = 1; n < m_iNoCols-1; n++ ) {
00749             // (1) (m,n)-->(m,n+1)   and (m,n)-->(m-1,n+1)
00750             m_pcParticle[m][n]->m_vtNormal 
00751                 = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n+1]->m_vtPosit) 
00752                   % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n+1]->m_vtPosit) ).Normalized();
00753             // (2) (m,n)-->(m-1,n+1) and (m,n)-->(m-1,n)
00754             m_pcParticle[m][n]->m_vtNormal 
00755                 += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n+1]->m_vtPosit) 
00756                    % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n  ]->m_vtPosit) ).Normalized();
00757             // (3) (m,n)-->(m-1,n)   and (m,n)-->(m-1,n-1)
00758             m_pcParticle[m][n]->m_vtNormal 
00759                 += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n  ]->m_vtPosit) 
00760                    % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n-1]->m_vtPosit) ).Normalized();
00761             // (4) (m,n)-->(m-1,n-1) and (m,n)-->(m,n-1)
00762             m_pcParticle[m][n]->m_vtNormal 
00763                 += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n-1]->m_vtPosit) 
00764                    % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n-1]->m_vtPosit) ).Normalized();
00765             // (5) (m,n)-->(m,n-1)   and (m,n)-->(m+1,n-1)
00766             m_pcParticle[m][n]->m_vtNormal 
00767                 += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n-1]->m_vtPosit) 
00768                    % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n-1]->m_vtPosit) ).Normalized();
00769             // (6) (m,n)-->(m+1,n-1) and (m,n)-->(m+1,n)
00770             m_pcParticle[m][n]->m_vtNormal 
00771                 += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n-1]->m_vtPosit) 
00772                    % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n  ]->m_vtPosit) ).Normalized();
00773             // (7) (m,n)-->(m+1,n)   and (m,n)-->(m+1,n+1)
00774             m_pcParticle[m][n]->m_vtNormal 
00775                 += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n  ]->m_vtPosit) 
00776                    % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n+1]->m_vtPosit) ).Normalized();
00777             // (8) (m,n)-->(m+1,n+1) and (m,n)-->(m,n+1)
00778             m_pcParticle[m][n]->m_vtNormal 
00779                 += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n+1]->m_vtPosit) 
00780                    % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n+1]->m_vtPosit) ).Normalized();
00781             // normalize the sum result vector
00782             m_pcParticle[m][n]->m_vtNormal.Normalized();
00783         }
00784     }
00785 
00786     //-------------------------------------------------------------------------
00787     // Normals of Particles on the Top Row (Except the Cornor Particle)
00788     m = 0;
00789     for ( n = 1; n < m_iNoCols-1; n++ ) {
00790         // (5) (m,n)-->(m,n-1)   and (m,n)-->(m+1,n-1)
00791         m_pcParticle[m][n]->m_vtNormal 
00792             = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n-1]->m_vtPosit) 
00793               % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n-1]->m_vtPosit) ).Normalized();
00794         // (6) (m,n)-->(m+1,n-1) and (m,n)-->(m+1,n)
00795         m_pcParticle[m][n]->m_vtNormal 
00796             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n-1]->m_vtPosit) 
00797                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n  ]->m_vtPosit) ).Normalized();
00798         // (7) (m,n)-->(m+1,n)   and (m,n)-->(m+1,n+1)
00799         m_pcParticle[m][n]->m_vtNormal 
00800             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n  ]->m_vtPosit) 
00801                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n+1]->m_vtPosit) ).Normalized();
00802         // (8) (m,n)-->(m+1,n+1) and (m,n)-->(m,n+1)
00803         m_pcParticle[m][n]->m_vtNormal 
00804             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n+1]->m_vtPosit) 
00805                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n+1]->m_vtPosit) ).Normalized();
00806         // normalize the sum result vector
00807         m_pcParticle[m][n]->m_vtNormal.Normalized();
00808     }
00809     //-------------------------------------------------------------------------
00810     // Normals of Particles on the Bottom Row (Except the Cornor Particle)
00811     m = m_iNoRows-1;
00812     for ( n = 1; n < m_iNoCols-1; n++ ) {
00813         // (1) (m,n)-->(m,n+1)   and (m,n)-->(m-1,n+1)
00814         m_pcParticle[m][n]->m_vtNormal 
00815             = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n+1]->m_vtPosit) 
00816               % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n+1]->m_vtPosit) ).Normalized();
00817         // (2) (m,n)-->(m-1,n+1) and (m,n)-->(m-1,n)
00818         m_pcParticle[m][n]->m_vtNormal 
00819             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n+1]->m_vtPosit) 
00820                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n  ]->m_vtPosit) ).Normalized();
00821         // (3) (m,n)-->(m-1,n)   and (m,n)-->(m-1,n-1)
00822         m_pcParticle[m][n]->m_vtNormal 
00823             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n  ]->m_vtPosit) 
00824                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n-1]->m_vtPosit) ).Normalized();
00825         // (4) (m,n)-->(m-1,n-1) and (m,n)-->(m,n-1)
00826         m_pcParticle[m][n]->m_vtNormal 
00827             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n-1]->m_vtPosit) 
00828                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n-1]->m_vtPosit) ).Normalized();
00829         // normalize the sum result vector
00830         m_pcParticle[m][n]->m_vtNormal.Normalized();
00831     }
00832     //-------------------------------------------------------------------------
00833     // Normals of Particles on the Left Column (Except the Cornor Particle)
00834     n = 0;
00835     for ( m = 1; m < m_iNoRows-1; m++ ) {
00836         // (7) (m,n)-->(m+1,n)   and (m,n)-->(m+1,n+1)
00837         m_pcParticle[m][n]->m_vtNormal 
00838             = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n  ]->m_vtPosit) 
00839               % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n+1]->m_vtPosit) ).Normalized();
00840         // (8) (m,n)-->(m+1,n+1) and (m,n)-->(m,n+1)
00841         m_pcParticle[m][n]->m_vtNormal 
00842             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n+1]->m_vtPosit) 
00843                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n+1]->m_vtPosit) ).Normalized();
00844         // (1) (m,n)-->(m,n+1)   and (m,n)-->(m-1,n+1)
00845         m_pcParticle[m][n]->m_vtNormal 
00846             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n+1]->m_vtPosit) 
00847                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n+1]->m_vtPosit) ).Normalized();
00848         // (2) (m,n)-->(m-1,n+1) and (m,n)-->(m-1,n)
00849         m_pcParticle[m][n]->m_vtNormal 
00850             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n+1]->m_vtPosit) 
00851                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n  ]->m_vtPosit) ).Normalized();
00852         // normalize the sum result vector
00853         m_pcParticle[m][n]->m_vtNormal.Normalized();
00854     }
00855     //-------------------------------------------------------------------------
00856     // Normals of Particles on the Right Row (Except the Cornor Particle)
00857     n = m_iNoCols-1;
00858     for ( m = 1; m < m_iNoRows-1; m++ ) {
00859         // (3) (m,n)-->(m-1,n)   and (m,n)-->(m-1,n-1)
00860         m_pcParticle[m][n]->m_vtNormal 
00861             = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n  ]->m_vtPosit) 
00862               % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n-1]->m_vtPosit) ).Normalized();
00863         // (4) (m,n)-->(m-1,n-1) and (m,n)-->(m,n-1)
00864         m_pcParticle[m][n]->m_vtNormal 
00865             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n-1]->m_vtPosit) 
00866                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n-1]->m_vtPosit) ).Normalized();
00867         // (5) (m,n)-->(m,n-1)   and (m,n)-->(m+1,n-1)
00868         m_pcParticle[m][n]->m_vtNormal 
00869             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n-1]->m_vtPosit) 
00870                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n-1]->m_vtPosit) ).Normalized();
00871         // (6) (m,n)-->(m+1,n-1) and (m,n)-->(m+1,n)
00872         m_pcParticle[m][n]->m_vtNormal 
00873             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n-1]->m_vtPosit) 
00874                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n  ]->m_vtPosit) ).Normalized();
00875         // normalize the sum result vector
00876         m_pcParticle[m][n]->m_vtNormal.Normalized();
00877     }
00878     
00879     // Top Left Cornor ---------------------------------------------------------
00880     m = 0; n = 0;
00881         // (7) (m,n)-->(m+1,n)   and (m,n)-->(m+1,n+1)
00882         m_pcParticle[m][n]->m_vtNormal 
00883             = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n  ]->m_vtPosit) 
00884               % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n+1]->m_vtPosit) ).Normalized();
00885         // (8) (m,n)-->(m+1,n+1) and (m,n)-->(m,n+1)
00886         m_pcParticle[m][n]->m_vtNormal 
00887             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n+1]->m_vtPosit) 
00888                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n+1]->m_vtPosit) ).Normalized();
00889         m_pcParticle[m][n]->m_vtNormal.Normalized();    // normalize the sum result vector
00890     // Bottom Left Cornor ------------------------------------------------------
00891     m = m_iNoRows-1; n = 0;
00892         // (1) (m,n)-->(m,n+1)   and (m,n)-->(m-1,n+1)
00893         m_pcParticle[m][n]->m_vtNormal 
00894             = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n+1]->m_vtPosit) 
00895               % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n+1]->m_vtPosit) ).Normalized();
00896         // (2) (m,n)-->(m-1,n+1) and (m,n)-->(m-1,n)
00897         m_pcParticle[m][n]->m_vtNormal 
00898             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n+1]->m_vtPosit) 
00899                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n  ]->m_vtPosit) ).Normalized();
00900         m_pcParticle[m][n]->m_vtNormal.Normalized();    // normalize the sum result vector
00901     // Bottom Right Cornor -----------------------------------------------------
00902     m = m_iNoRows-1; n = m_iNoCols-1;
00903         // (3) (m,n)-->(m-1,n)   and (m,n)-->(m-1,n-1)
00904         m_pcParticle[m][n]->m_vtNormal 
00905             = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n  ]->m_vtPosit) 
00906               % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n-1]->m_vtPosit) ).Normalized();
00907         // (4) (m,n)-->(m-1,n-1) and (m,n)-->(m,n-1)
00908         m_pcParticle[m][n]->m_vtNormal 
00909             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m-1][n-1]->m_vtPosit) 
00910                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n-1]->m_vtPosit) ).Normalized();
00911         m_pcParticle[m][n]->m_vtNormal.Normalized();    // normalize the sum result vector
00912     // Top Right Cornor --------------------------------------------------------
00913     m = 0; n = m_iNoCols-1;
00914         // (5) (m,n)-->(m,n-1)   and (m,n)-->(m+1,n-1)
00915         m_pcParticle[m][n]->m_vtNormal 
00916             = ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m  ][n-1]->m_vtPosit) 
00917               % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n-1]->m_vtPosit) ).Normalized();
00918         // (6) (m,n)-->(m+1,n-1) and (m,n)-->(m+1,n)
00919         m_pcParticle[m][n]->m_vtNormal 
00920             += ( (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n-1]->m_vtPosit) 
00921                % (m_pcParticle[m][n]->m_vtPosit - m_pcParticle[m+1][n  ]->m_vtPosit) ).Normalized();
00922         m_pcParticle[m][n]->m_vtNormal.Normalized();    // normalize the sum result vector
00923 }
00924 //-------------------------------------------------------------------------------------------------
00925 // Calculate Particle Normals
00926 template <typename T>
00927 void Cloth<T>::CalParticleNormals( int i )
00928 {
00929 /*
00930     -----------------
00931     | \  3  |  2  / |
00932     |   \   |   /   |
00933     | 4   \ | /  1  |   Normal of the middle (m,n) particle is the sum of the eight normals.
00934     |<------+------>|   E.g. normal 1 is the unit vector of the cross product of (m,n)-->(m,n+1) 
00935     | 5   / | \  8  |   vector with (m,n)-->(m-1,n+1) vector (rotated counter clockwise).
00936     |   /   |   \   |
00937     | /  6  |  7  \ |
00938     -----------------
00939 */
00940     // These particles have all 8 neighbors ------------------------------------
00941     for ( m = 1; m < m_iNoRows-1; m++ ) {
00942         for ( n = 1; n < m_iNoCols-1; n++ ) {
00943             // (1) (m,n)-->(m,n+1)   and (m,n)-->(m-1,n+1)
00944             m_pcParticle[m  ][n  ]->m_vtNormal[0] = 0;
00945             m_pcParticle[m  ][n  ]->m_vtNormal[1] = 0;
00946             m_pcParticle[m  ][n  ]->m_vtNormal[2] = 0;
00947             AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
00948                        m_pcParticle[m  ][n  ]->m_vtPosit,
00949                        m_pcParticle[m  ][n+1]->m_vtPosit,
00950                        m_pcParticle[m-1][n+1]->m_vtPosit );
00951             // (2) (m,n)-->(m-1,n+1) and (m,n)-->(m-1,n)
00952             AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
00953                        m_pcParticle[m  ][n  ]->m_vtPosit,
00954                        m_pcParticle[m-1][n+1]->m_vtPosit,
00955                        m_pcParticle[m-1][n  ]->m_vtPosit );
00956             // (3) (m,n)-->(m-1,n)   and (m,n)-->(m-1,n-1)
00957             AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
00958                        m_pcParticle[m  ][n  ]->m_vtPosit,
00959                        m_pcParticle[m-1][n  ]->m_vtPosit,
00960                        m_pcParticle[m-1][n-1]->m_vtPosit );
00961             // (4) (m,n)-->(m-1,n-1) and (m,n)-->(m,n-1)
00962             AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
00963                        m_pcParticle[m  ][n  ]->m_vtPosit,
00964                        m_pcParticle[m-1][n-1]->m_vtPosit,
00965                        m_pcParticle[m  ][n-1]->m_vtPosit );
00966             // (5) (m,n)-->(m,n-1)   and (m,n)-->(m+1,n-1)
00967             AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
00968                        m_pcParticle[m  ][n  ]->m_vtPosit,
00969                        m_pcParticle[m  ][n-1]->m_vtPosit,
00970                        m_pcParticle[m+1][n-1]->m_vtPosit );
00971             // (6) (m,n)-->(m+1,n-1) and (m,n)-->(m+1,n)
00972             AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
00973                        m_pcParticle[m  ][n  ]->m_vtPosit,
00974                        m_pcParticle[m+1][n-1]->m_vtPosit,
00975                        m_pcParticle[m+1][n  ]->m_vtPosit );
00976             // (7) (m,n)-->(m+1,n)   and (m,n)-->(m+1,n+1)
00977             AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
00978                        m_pcParticle[m  ][n  ]->m_vtPosit,
00979                        m_pcParticle[m+1][n  ]->m_vtPosit,
00980                        m_pcParticle[m+1][n+1]->m_vtPosit );
00981             // (8) (m,n)-->(m+1,n+1) and (m,n)-->(m,n+1)
00982             AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
00983                        m_pcParticle[m  ][n  ]->m_vtPosit,
00984                        m_pcParticle[m+1][n+1]->m_vtPosit,
00985                        m_pcParticle[m  ][n+1]->m_vtPosit );
00986             // normalize the sum result vector
00987             m_pcParticle[m][n]->m_vtNormal.Normalized();
00988         }
00989     }
00990 
00991     //-------------------------------------------------------------------------
00992     // Normals of Particles on the Top Row (Except the Cornor Particle)
00993     m = 0;
00994     for ( n = 1; n < m_iNoCols-1; n++ ) {
00995         // (5) (m,n)-->(m,n-1)   and (m,n)-->(m+1,n-1)
00996         m_pcParticle[m][n]->m_vtNormal[0] = 0;
00997         m_pcParticle[m][n]->m_vtNormal[1] = 0;
00998         m_pcParticle[m][n]->m_vtNormal[2] = 0;
00999         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01000                    m_pcParticle[m  ][n  ]->m_vtPosit,
01001                    m_pcParticle[m  ][n-1]->m_vtPosit,
01002                    m_pcParticle[m+1][n-1]->m_vtPosit );
01003         // (6) (m,n)-->(m+1,n-1) and (m,n)-->(m+1,n)
01004         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01005                    m_pcParticle[m  ][n  ]->m_vtPosit,
01006                    m_pcParticle[m+1][n-1]->m_vtPosit,
01007                    m_pcParticle[m+1][n  ]->m_vtPosit );
01008         // (7) (m,n)-->(m+1,n)   and (m,n)-->(m+1,n+1)
01009         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01010                    m_pcParticle[m  ][n  ]->m_vtPosit,
01011                    m_pcParticle[m+1][n  ]->m_vtPosit,
01012                    m_pcParticle[m+1][n+1]->m_vtPosit );
01013         // (8) (m,n)-->(m+1,n+1) and (m,n)-->(m,n+1)
01014         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01015                    m_pcParticle[m  ][n  ]->m_vtPosit,
01016                    m_pcParticle[m+1][n+1]->m_vtPosit,
01017                    m_pcParticle[m  ][n+1]->m_vtPosit );
01018         // normalize the sum result vector
01019         m_pcParticle[m][n]->m_vtNormal.Normalized();
01020     }
01021     //-------------------------------------------------------------------------
01022     // Normals of Particles on the Bottom Row (Except the Cornor Particle)
01023     m = m_iNoRows-1;
01024     for ( n = 1; n < m_iNoCols-1; n++ ) {
01025         // (1) (m,n)-->(m,n+1)   and (m,n)-->(m-1,n+1)
01026         m_pcParticle[m][n]->m_vtNormal[0] = 0;
01027         m_pcParticle[m][n]->m_vtNormal[1] = 0;
01028         m_pcParticle[m][n]->m_vtNormal[2] = 0;
01029         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01030                    m_pcParticle[m  ][n  ]->m_vtPosit,
01031                    m_pcParticle[m  ][n+1]->m_vtPosit,
01032                    m_pcParticle[m-1][n+1]->m_vtPosit );
01033         // (2) (m,n)-->(m-1,n+1) and (m,n)-->(m-1,n)
01034         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01035                    m_pcParticle[m  ][n  ]->m_vtPosit,
01036                    m_pcParticle[m-1][n+1]->m_vtPosit,
01037                    m_pcParticle[m-1][n  ]->m_vtPosit );
01038         // (3) (m,n)-->(m-1,n)   and (m,n)-->(m-1,n-1)
01039         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01040                    m_pcParticle[m  ][n  ]->m_vtPosit,
01041                    m_pcParticle[m-1][n  ]->m_vtPosit,
01042                    m_pcParticle[m-1][n-1]->m_vtPosit );
01043         // (4) (m,n)-->(m-1,n-1) and (m,n)-->(m,n-1)
01044         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01045                    m_pcParticle[m  ][n  ]->m_vtPosit,
01046                    m_pcParticle[m-1][n-1]->m_vtPosit,
01047                    m_pcParticle[m  ][n-1]->m_vtPosit );
01048         // normalize the sum result vector
01049         m_pcParticle[m][n]->m_vtNormal.Normalized();
01050     }
01051     //-------------------------------------------------------------------------
01052     // Normals of Particles on the Left Column (Except the Cornor Particle)
01053     n = 0;
01054     for ( m = 1; m < m_iNoRows-1; m++ ) {
01055         // (7) (m,n)-->(m+1,n)   and (m,n)-->(m+1,n+1)
01056         m_pcParticle[m][n]->m_vtNormal[0] = 0;
01057         m_pcParticle[m][n]->m_vtNormal[1] = 0;
01058         m_pcParticle[m][n]->m_vtNormal[2] = 0;
01059         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01060                    m_pcParticle[m  ][n  ]->m_vtPosit,
01061                    m_pcParticle[m+1][n  ]->m_vtPosit,
01062                    m_pcParticle[m+1][n+1]->m_vtPosit );
01063         // (8) (m,n)-->(m+1,n+1) and (m,n)-->(m,n+1)
01064         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01065                    m_pcParticle[m  ][n  ]->m_vtPosit,
01066                    m_pcParticle[m+1][n+1]->m_vtPosit,
01067                    m_pcParticle[m  ][n+1]->m_vtPosit );
01068         // (1) (m,n)-->(m,n+1)   and (m,n)-->(m-1,n+1)
01069         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01070                    m_pcParticle[m  ][n  ]->m_vtPosit,
01071                    m_pcParticle[m  ][n+1]->m_vtPosit,
01072                    m_pcParticle[m-1][n+1]->m_vtPosit );
01073         // (2) (m,n)-->(m-1,n+1) and (m,n)-->(m-1,n)
01074         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01075                    m_pcParticle[m  ][n  ]->m_vtPosit,
01076                    m_pcParticle[m-1][n+1]->m_vtPosit,
01077                    m_pcParticle[m-1][n  ]->m_vtPosit );
01078         // normalize the sum result vector
01079         m_pcParticle[m][n]->m_vtNormal.Normalized();
01080     }
01081     //-------------------------------------------------------------------------
01082     // Normals of Particles on the Right Row (Except the Cornor Particle)
01083     n = m_iNoCols-1;
01084     for ( m = 1; m < m_iNoRows-1; m++ ) {
01085         // (3) (m,n)-->(m-1,n)   and (m,n)-->(m-1,n-1)
01086         m_pcParticle[m][n]->m_vtNormal[0] = 0;
01087         m_pcParticle[m][n]->m_vtNormal[1] = 0;
01088         m_pcParticle[m][n]->m_vtNormal[2] = 0;
01089         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01090                    m_pcParticle[m  ][n  ]->m_vtPosit,
01091                    m_pcParticle[m-1][n  ]->m_vtPosit,
01092                    m_pcParticle[m-1][n-1]->m_vtPosit );
01093         // (4) (m,n)-->(m-1,n-1) and (m,n)-->(m,n-1)
01094         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01095                    m_pcParticle[m  ][n  ]->m_vtPosit,
01096                    m_pcParticle[m-1][n-1]->m_vtPosit,
01097                    m_pcParticle[m  ][n-1]->m_vtPosit );
01098         // (5) (m,n)-->(m,n-1)   and (m,n)-->(m+1,n-1)
01099         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01100                    m_pcParticle[m  ][n  ]->m_vtPosit,
01101                    m_pcParticle[m  ][n-1]->m_vtPosit,
01102                    m_pcParticle[m+1][n-1]->m_vtPosit );
01103         // (6) (m,n)-->(m+1,n-1) and (m,n)-->(m+1,n)
01104         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01105                    m_pcParticle[m  ][n  ]->m_vtPosit,
01106                    m_pcParticle[m+1][n-1]->m_vtPosit,
01107                    m_pcParticle[m+1][n  ]->m_vtPosit );
01108         // normalize the sum result vector
01109         m_pcParticle[m][n]->m_vtNormal.Normalized();
01110     }
01111     
01112     // Top Left Cornor ---------------------------------------------------------
01113     m = 0; n = 0;
01114         // (7) (m,n)-->(m+1,n)   and (m,n)-->(m+1,n+1)
01115         m_pcParticle[m][n]->m_vtNormal[0] = 0;
01116         m_pcParticle[m][n]->m_vtNormal[1] = 0;
01117         m_pcParticle[m][n]->m_vtNormal[2] = 0;
01118         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01119                    m_pcParticle[m  ][n  ]->m_vtPosit,
01120                    m_pcParticle[m+1][n  ]->m_vtPosit,
01121                    m_pcParticle[m+1][n+1]->m_vtPosit );
01122         // (8) (m,n)-->(m+1,n+1) and (m,n)-->(m,n+1)
01123         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01124                    m_pcParticle[m  ][n  ]->m_vtPosit,
01125                    m_pcParticle[m+1][n+1]->m_vtPosit,
01126                    m_pcParticle[m  ][n+1]->m_vtPosit );
01127         m_pcParticle[m][n]->m_vtNormal.Normalized();    // normalize the sum result vector
01128     // Bottom Left Cornor ------------------------------------------------------
01129     m = m_iNoRows-1; n = 0;
01130         // (1) (m,n)-->(m,n+1)   and (m,n)-->(m-1,n+1)
01131         m_pcParticle[m][n]->m_vtNormal[0] = 0;
01132         m_pcParticle[m][n]->m_vtNormal[1] = 0;
01133         m_pcParticle[m][n]->m_vtNormal[2] = 0;
01134         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01135                    m_pcParticle[m  ][n  ]->m_vtPosit,
01136                    m_pcParticle[m  ][n+1]->m_vtPosit,
01137                    m_pcParticle[m-1][n+1]->m_vtPosit );
01138         // (2) (m,n)-->(m-1,n+1) and (m,n)-->(m-1,n)
01139         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01140                    m_pcParticle[m  ][n  ]->m_vtPosit,
01141                    m_pcParticle[m-1][n+1]->m_vtPosit,
01142                    m_pcParticle[m-1][n  ]->m_vtPosit );
01143         m_pcParticle[m][n]->m_vtNormal.Normalized();    // normalize the sum result vector
01144     // Bottom Right Cornor -----------------------------------------------------
01145     m = m_iNoRows-1; n = m_iNoCols-1;
01146         // (3) (m,n)-->(m-1,n)   and (m,n)-->(m-1,n-1)
01147         m_pcParticle[m][n]->m_vtNormal[0] = 0;
01148         m_pcParticle[m][n]->m_vtNormal[1] = 0;
01149         m_pcParticle[m][n]->m_vtNormal[2] = 0;
01150         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01151                    m_pcParticle[m  ][n  ]->m_vtPosit,
01152                    m_pcParticle[m-1][n  ]->m_vtPosit,
01153                    m_pcParticle[m-1][n-1]->m_vtPosit );
01154         // (4) (m,n)-->(m-1,n-1) and (m,n)-->(m,n-1)
01155         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01156                    m_pcParticle[m  ][n  ]->m_vtPosit,
01157                    m_pcParticle[m-1][n-1]->m_vtPosit,
01158                    m_pcParticle[m  ][n-1]->m_vtPosit );
01159         m_pcParticle[m][n]->m_vtNormal.Normalized();    // normalize the sum result vector
01160     // Top Right Cornor --------------------------------------------------------
01161     m = 0; n = m_iNoCols-1;
01162         // (5) (m,n)-->(m,n-1)   and (m,n)-->(m+1,n-1)
01163         m_pcParticle[m][n]->m_vtNormal[0] = 0;
01164         m_pcParticle[m][n]->m_vtNormal[1] = 0;
01165         m_pcParticle[m][n]->m_vtNormal[2] = 0;
01166         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01167                    m_pcParticle[m  ][n  ]->m_vtPosit,
01168                    m_pcParticle[m  ][n-1]->m_vtPosit,
01169                    m_pcParticle[m+1][n-1]->m_vtPosit );
01170         // (6) (m,n)-->(m+1,n-1) and (m,n)-->(m+1,n)
01171         AddNormal( m_pcParticle[m  ][n  ]->m_vtNormal,
01172                    m_pcParticle[m  ][n  ]->m_vtPosit,
01173                    m_pcParticle[m+1][n-1]->m_vtPosit,
01174                    m_pcParticle[m+1][n  ]->m_vtPosit );
01175         m_pcParticle[m][n]->m_vtNormal.Normalized();    // normalize the sum result vector
01176 }
01177 /*
01178 //-------------------------------------------------------------------------------------------------
01179 // Clear Force of Particles to Zeros
01180 template <typename T>
01181 void Cloth<T>::ClearForce()
01182 {
01183     T x = 0, y = 0, z = 0;
01184     for ( m = 0; m < m_iNoRows; m++ ) {
01185         for ( n = 0; n < m_iNoCols; n++ ) {
01186             m_pcParticle[m][n]->m_vtForce( x, y, z );
01187         }
01188     }
01189 }
01190 //-------------------------------------------------------------------------------------------------
01191 // Calculate (Weight) Force due to (Acceleration of) Gravity
01192 template <typename T>
01193 void Cloth<T>::ForceDueToGravity( T g )
01194 {
01195     
01196 }
01197 //-------------------------------------------------------------------------------------------------
01198 // Calculate (a Loss) Force due to Viscous Damping
01199 template <typename T>
01200 void Cloth<T>::ForceDueToViscousDamping()
01201 {
01202 }
01203 //-------------------------------------------------------------------------------------------------
01204 // Calculate (Wind) Force due to Viscous Fluid Moving
01205 template <typename T>
01206 void Cloth<T>::ForceDueToViscousFluidMoving()
01207 {
01208 }
01209 */
01210 //-------------------------------------------------------------------------------------------------
01211 // Calculate All Forces Acting on Particles
01212 template <typename T>
01213 void Cloth<T>::CalForces( Vector3<T> vWind, T g )
01214 {
01215     CalParticleNormals( 0 );    // calculate particle normals use for finding force due to wind
01216 
01217     T zero = 0, y = 0;
01218     for ( m = 0; m < m_iNoRows; m++ ) {
01219         for ( n = 0; n < m_iNoCols; n++ ) {
01220             if ( m_pcParticle[m][n]->m_bFixed ) {       // If the particle is fixed, skip it!
01221                 m_pcParticle[m][n]->m_vtForce[0] =
01222                 m_pcParticle[m][n]->m_vtForce[1] =
01223                 m_pcParticle[m][n]->m_vtForce[2] = zero;
01224                 continue;
01225             }
01226             // Clear and Calculate Force due to Acceleration of Gravity --------
01227             //     Fij = mass * g; where g is a vector
01228             y = m_pcParticle[m][n]->m_tMass * (-g);
01229             m_pcParticle[m][n]->m_vtForce[0] = zero;
01230             m_pcParticle[m][n]->m_vtForce[1] = y;
01231             m_pcParticle[m][n]->m_vtForce[2] = zero;
01232             // Add Force due to Viscous Damping --------------------------------
01233             //     Fij = -Kvd * Vij
01234             m_pcParticle[m][n]->m_vtForce += m_tKvd * m_pcParticle[m][n]->m_vtVeloc;
01235             // Add Force due to viscous fluid moving (wind) --------------------
01236             //     Fij = Kvfm * [Nij * (vWind - Vij)] * Nij
01237             //         where Nij is the unit normal on the surface at particle Pij
01238             m_pcParticle[m][n]->m_vtForce +=  m_tKvfm 
01239                                             * ( m_pcParticle[m][n]->m_vtNormal * ( vWind - m_pcParticle[m][n]->m_vtVeloc ) )
01240                                             * m_pcParticle[m][n]->m_vtNormal;
01241 
01242             // Dump
01243             //cout << "Mass: " << m_pcParticle[m][n]->m_tMass << "    Force: " << m_pcParticle[m][n]->m_vtForce << "\n";
01244         }
01245     }
01246     
01247     AddSpringForces();  // calculate and add spring forces to particle forces
01248 }
01249 //-------------------------------------------------------------------------------------------------
01250 // Display Via OpenGL
01251 template <typename T>
01252 void Cloth<T>::DisplayGL( OpenGL::Enum::DrawMode DM )
01253 {
01254     //int ptSize[1];
01255     glColor3f( 1.0f, 1.0f, 1.0f );
01256 
01257     int count;
01258     for ( count = 0; count < 8; count++ ) {
01259         StepSimulation( 0.001 );
01260         //StepSimulation( 0.0005 );
01261         //StepSimulation( 0.0001 );
01262     }
01263 
01264     //SetMaterial( OpenGL::Enum::METAL_GOLD );
01265     //SetMaterial( OpenGL::Enum::METAL_SILVER );
01266     //SetMaterial( OpenGL::Enum::METAL_BRONZE );
01267     SetMaterial( OpenGL::Enum::BLUE_01 );
01268     ApplyMaterial( OpenGL::Enum::FRONT );
01269     SetMaterial( OpenGL::Enum::METAL_GOLD );
01270     material.ApplyMaterial( OpenGL::Enum::BACK );
01271     
01272     switch (DM) {
01273         // Draw Points for Cloth
01274         case OpenGL::Enum::POINT:
01275             // Set Point Size
01276             //glGetIntegerv( GL_POINT_SIZE, ptSize );
01277             //glPointSize( 2 );
01278             glBegin( GL_POINTS );
01279             for ( m = 0; m < m_iNoRows; m++ ) {
01280                 for ( n = 0; n < m_iNoCols; n++ ) {
01281                     glVertex3f( m_pcParticle[m][n]->m_vtPosit[0], 
01282                                 m_pcParticle[m][n]->m_vtPosit[1],
01283                                 m_pcParticle[m][n]->m_vtPosit[2] );
01284                 }
01285             }
01286             glEnd();
01287             // Restore Point Size
01288             //glPointSize( ptSize[0] );
01289             break;
01290 
01291         // Draw Wire Frame for Cloth
01292         case OpenGL::Enum::WIRE_FRAME:
01293             glColor3f(0,0,0.5);
01294             glDisable(GL_LIGHTING);
01295             // Draw Row Lines
01296             for ( m = 0; m < m_iNoRows; m++ ) {
01297                 glBegin( GL_LINE_STRIP );
01298                 for ( n = 0; n < m_iNoCols; n++ ) {
01299                     glVertex3f( m_pcParticle[m][n]->m_vtPosit[0], 
01300                                 m_pcParticle[m][n]->m_vtPosit[1],
01301                                 m_pcParticle[m][n]->m_vtPosit[2] );
01302                 }
01303                 glEnd();
01304             }
01305             // Draw Column Lines
01306             for ( n = 0; n < m_iNoCols; n++ ) {
01307                 glBegin( GL_LINE_STRIP );
01308                 for ( m = 0; m < m_iNoRows; m++ ) {
01309                     glVertex3f( m_pcParticle[m][n]->m_vtPosit[0], 
01310                                 m_pcParticle[m][n]->m_vtPosit[1],
01311                                 m_pcParticle[m][n]->m_vtPosit[2] );
01312                 }
01313                 glEnd();
01314             }
01315             // Draw Diagonal Lines
01316             glBegin( GL_LINES );
01317             for ( m = 0; m < m_iNoRows-1; m++ ) {
01318                 for ( n = 0; n < m_iNoCols-1; n++ ) {
01319                     // Draw a line from [m][n] --- [m+1][n+1]
01320                     glVertex3f( m_pcParticle[m][n]->m_vtPosit[0], 
01321                                 m_pcParticle[m][n]->m_vtPosit[1],
01322                                 m_pcParticle[m][n]->m_vtPosit[2] );
01323                     glVertex3f( m_pcParticle[m+1][n+1]->m_vtPosit[0], 
01324                                 m_pcParticle[m+1][n+1]->m_vtPosit[1],
01325                                 m_pcParticle[m+1][n+1]->m_vtPosit[2] );
01326                     // Draw a line from [m+1][n] to [m][n+1]
01327                     glVertex3f( m_pcParticle[m+1][n]->m_vtPosit[0], 
01328                                 m_pcParticle[m+1][n]->m_vtPosit[1],
01329                                 m_pcParticle[m+1][n]->m_vtPosit[2] );
01330                     glVertex3f( m_pcParticle[m][n+1]->m_vtPosit[0], 
01331                                 m_pcParticle[m][n+1]->m_vtPosit[1],
01332                                 m_pcParticle[m][n+1]->m_vtPosit[2] );
01333                 }
01334             }
01335             glEnd();
01336             glEnable(GL_LIGHTING);
01337             break;
01338 
01339         // Draw Polygons for Cloth
01340         case OpenGL::Enum::POLYGON:
01341             // With Texture
01342             if ( m_pcImg != NULL ) {
01343 
01344                 DrawTexture();
01345                 //EnableTexture();
01346 
01347                 float tr, tc;
01348                 float trStep = 1.0 / (m_iNoRows-1);
01349                 float tcStep = 1.0 / (m_iNoCols-1);
01350                 for ( m = 0, tr = 1.0; m < m_iNoRows-1; m++, tr -= trStep ) {
01351                     glBegin( GL_QUAD_STRIP );
01352                     for ( n = 0, tc = 0.0; n < m_iNoCols; n++, tc += tcStep ) {
01353                         glNormal3f( m_pcParticle[m][n]->m_vtNormal[0], 
01354                                     m_pcParticle[m][n]->m_vtNormal[1],
01355                                     m_pcParticle[m][n]->m_vtNormal[2] );
01356                         glTexCoord2f(tc, tr);
01357                         glVertex3f( m_pcParticle[m][n]->m_vtPosit[0], 
01358                                     m_pcParticle[m][n]->m_vtPosit[1],
01359                                     m_pcParticle[m][n]->m_vtPosit[2] );
01360 
01361                         glNormal3f( m_pcParticle[m+1][n]->m_vtNormal[0], 
01362                                     m_pcParticle[m+1][n]->m_vtNormal[1],
01363                                     m_pcParticle[m+1][n]->m_vtNormal[2] );
01364                         glTexCoord2f(tc, tr-trStep);
01365                         glVertex3f( m_pcParticle[m+1][n]->m_vtPosit[0], 
01366                                     m_pcParticle[m+1][n]->m_vtPosit[1],
01367                                     m_pcParticle[m+1][n]->m_vtPosit[2] );
01368                     }
01369                     glEnd();
01370                 }
01371             }
01372             // Without Texture
01373             else {
01374                 for ( m = 0; m < m_iNoRows-1; m++ ) {
01375                     glBegin( GL_QUAD_STRIP );
01376                     for ( n = 0; n < m_iNoCols; n++ ) {
01377                         glNormal3f( m_pcParticle[m][n]->m_vtNormal[0], 
01378                                     m_pcParticle[m][n]->m_vtNormal[1],
01379                                     m_pcParticle[m][n]->m_vtNormal[2] );
01380                         glVertex3f( m_pcParticle[m][n]->m_vtPosit[0], 
01381                                     m_pcParticle[m][n]->m_vtPosit[1],
01382                                     m_pcParticle[m][n]->m_vtPosit[2] );
01383 
01384                         glNormal3f( m_pcParticle[m+1][n]->m_vtNormal[0], 
01385                                     m_pcParticle[m+1][n]->m_vtNormal[1],
01386                                     m_pcParticle[m+1][n]->m_vtNormal[2] );
01387                         glVertex3f( m_pcParticle[m+1][n]->m_vtPosit[0], 
01388                                     m_pcParticle[m+1][n]->m_vtPosit[1],
01389                                     m_pcParticle[m+1][n]->m_vtPosit[2] );
01390                     }
01391                     glEnd();
01392                 }
01393             }
01394             break;
01395     }
01396 
01397     // TEST
01398     //DisplayGL_ParticleNormals();
01399     
01400     glDisable( GL_LIGHTING );
01401     glColor3f( 0.0f, 1.0f, 0.0f );
01402     glPointSize( 7 );
01403     m = 0; n = 0;
01404     glBegin( GL_POINTS );
01405         glVertex3f( m_pcParticle[m][n]->m_vtPosit[0], 
01406                     m_pcParticle[m][n]->m_vtPosit[1],
01407                     m_pcParticle[m][n]->m_vtPosit[2] );
01408     glEnd();
01409     glColor3f( 0.0f, 1.0f, 1.0f );
01410     glPointSize( 5 );
01411     m = 0; n = 1;
01412     glBegin( GL_POINTS );
01413         glVertex3f( m_pcParticle[m][n]->m_vtPosit[0], 
01414                     m_pcParticle[m][n]->m_vtPosit[1],
01415                     m_pcParticle[m][n]->m_vtPosit[2] );
01416     glEnd();
01417     glPointSize( 1 );
01418     glEnable( GL_LIGHTING );
01419     // END TEST
01420 }
01421 //-------------------------------------------------------------------------------------------------
01422 // Display Particle Normals Via OpenGL
01423 template <typename T>
01424 void Cloth<T>::DisplayGL_ParticleNormals()
01425 {
01426     T x, y, z;
01427 
01428     // Draw Normal of each particle
01429     glDisable( GL_LIGHTING );
01430     glColor3f( 1.0f, 0.0f, 0.0f );
01431     glBegin( GL_LINES );
01432     for ( m = 0; m < m_iNoRows; m++ ) {
01433         for ( n = 0; n < m_iNoCols; n++ ) {
01434             m_pcParticle[m][n]->m_vtPosit.GetXYZ( x, y, z );
01435             glVertex3f( x, y, z );
01436             glVertex3f( x + m_pcParticle[m][n]->m_vtNormal[0], 
01437                         y + m_pcParticle[m][n]->m_vtNormal[1],
01438                         z + m_pcParticle[m][n]->m_vtNormal[2] );
01439         }
01440     }
01441     glEnd();
01442     glEnable( GL_LIGHTING );
01443 }
01444 //================================================================================================
01445 // FRIEND FUNCTIONS
01446 //-------------------------------------------------------------------------------------------------
01447 // put it through ostream
01448 /*template <typename T>
01449 ostream &operator<<( ostream &output, const Cloth<T> &Obj )
01450 {
01451     output  << "Cloth ==> "
01452             << "\n  number of rows:       " << Obj.m_iNoRows
01453             << "\n  number of columns:    " << Obj.m_iNoCols
01454             << "\n  viscous damping:      " << Obj.m_tKvd
01455             << "\n  wind damping:         " << Obj.m_tKvfm
01456             << "\n  stiffness of structural, shear, and flexion springs: " 
01457                     << Obj.m_tKs[0] << ", " << Obj.m_tKs[1] << ", and " << Obj.m_tKs[2]
01458             << "\n  damping constant for structural, shear, and flexion springs: "
01459                     << Obj.m_tKd[0] << ", " << Obj.m_tKd[1] << ", and " << Obj.m_tKd[2]
01460             << "\n  length constrain for structural, shear, and flextion springs: "
01461                     << Obj.m_tLengthConstrain[0] << ", " 
01462                     << Obj.m_tLengthConstrain[1] << ", and " 
01463                     << Obj.m_tLengthConstrain[2]
01464             << "\n";
01465 
01466     return output;
01467 }*/
01468 
01469 template <typename T>
01470 void Cloth<T>::AddNormal( Vector3<T> & Dest, 
01471                        Vector3<T> const & A, Vector3<T> const & B, Vector3<T> const & C )
01472 {
01473     T U[3] = { A[0]-B[0], A[1]-B[1], A[2]-B[2] };
01474     T V[3] = { A[0]-C[0], A[1]-C[1], A[2]-C[2] };
01475     T W[3] = { U[1]*V[2] - U[2]*V[1], U[2]*V[0] - U[0]*V[2], U[0]*V[1] - U[1]*V[0] };
01476     T SqrtLength = Math<T>::Sqrt( W[0]*W[0] + W[1]*W[1] + W[2]*W[2] );
01477     Dest[0] += W[0]/SqrtLength;
01478     Dest[1] += W[1]/SqrtLength;
01479     Dest[2] += W[2]/SqrtLength;
01480 }
01481 //MEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERMEMBERME
01482 
01483 
01484 //=============================================================================
01485 END_NAMESPACE_TAPs
01486 //-----------------------------------------------------------------------------
01487 #endif
01488 //345678901234567890123456789012345678901234567890123456789012345678901234567890
01489 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines