00001 ////////////////////////////////////////////////////////////////////// 00002 // Copyright (c) 2002-2003 David Pritchard <drpritch@alumni.uwaterloo.ca> 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either 00007 // version 2 of the License, or (at your option) any later 00008 // version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 00019 #ifndef freecloth_sim_simSimulator_h 00020 #define freecloth_sim_simSimulator_h 00021 00022 #ifndef freecloth_sim_package_h 00023 #include <freecloth/simulator/package.h> 00024 #endif 00025 00026 #ifndef freecloth_sim_simMatrix_h 00027 #include <freecloth/simulator/simMatrix.h> 00028 #endif 00029 00030 #ifndef freecloth_sim_simVector_h 00031 #include <freecloth/simulator/simVector.h> 00032 #endif 00033 00034 #ifndef freecloth_base_algorithm 00035 #include <freecloth/base/algorithm> 00036 #endif 00037 00038 #ifndef freecloth_base_list 00039 #include <freecloth/base/list> 00040 #endif 00041 00042 #ifndef freecloth_base_baTime_h 00043 #include <freecloth/base/baTime.h> 00044 #endif 00045 00046 #ifndef freecloth_resmgt_rcShdPtr_h 00047 #include <freecloth/resmgt/rcShdPtr.h> 00048 #endif 00049 00050 #ifndef freecloth_resmgt_rcBase_h 00051 #include <freecloth/resmgt/rcBase.h> 00052 #endif 00053 00054 #ifndef freecloth_geom_geMesh_h 00055 #include <freecloth/geom/geMesh.h> 00056 #endif 00057 00058 #ifndef freecloth_geom_geMeshWingedEdge_h 00059 #include <freecloth/geom/geMeshWingedEdge.h> 00060 #endif 00061 00062 FREECLOTH_NAMESPACE_START 00063 00064 //////////////////////////////////////////////////////////////////////////////// 00065 // FORWARD DECLARATIONS 00066 00067 class GeMatrix3; 00068 00069 //////////////////////////////////////////////////////////////////////////////// 00070 /*! 00071 * \class SimSimulator freecloth/simulator/simSimulator.h 00072 * \brief An implementation of Baraff & Witkin's cloth simulation algorithm. 00073 * 00074 * Using the simulation is fairly straightforward. The client supplies an 00075 * initial mesh, which must have disc topology. The client also specifies the 00076 * density of the cloth, which indirectly defines the mass of each triangle of 00077 * the mesh. The client can also specify constraints on the cloth motion, 00078 * constraining both the position and the velocity of individual nodes of the 00079 * mesh. 00080 * 00081 * Time starts at zero, and is advanced by a fixed timestep by calls to step(). 00082 * The client can retrieve the mesh after each timestep. The simulation can 00083 * be rewound to the beginning by calling rewind(). 00084 * 00085 * There are many parameters for the simulation algorithm. See [BarWit98] or 00086 * the description in SimSimulator::Params for details. 00087 * 00088 * Test: \f$ \w \f$ 00089 * 00090 * References: 00091 * - [BarWit98] D. Baraff and A. Witkin. Large Steps in Cloth Simulation. 00092 * SIGGRAPH Conference Proceedings, 1998, 43-54. 00093 * http://www-2.cs.cmu.edu/~baraff/papers/sig98.pdf 00094 * - [Pri02] D. Pritchard. "Implementing Baraff & Witkin's Cloth Simulation". 00095 * Unpublished, 2002. 00096 * http://freecloth.enigmati.ca/docs/report-chaps/ 00097 * - [Mac00] D. Macri. Real-Time Cloth. Game Developers Conference, 2000. 00098 * http://www.gdconf.com/archives/2000/macri.doc 00099 */ 00100 00101 // FIXME: the mesh should be allowed to have cylindrical or spherical 00102 // topology, not just disc topology. 00103 // 00104 // FIXME: should really implement this as a Bridge pattern, to hide the 00105 // implementation from clients better. 00106 class SimSimulator : public RCBase 00107 { 00108 public: 00109 // ----- classes ----- 00110 //////////////////////////////////////////////////////////////////////////// 00111 /*! 00112 * \class Params freecloth/simulator/simSimulator.h 00113 * \brief Parameters for cloth simulator, as described in [BarWit98]. 00114 * 00115 * The stretch, shear, and bend parameters control the strength of the 00116 * associated internal forces. For example, a higher _k_stretch value 00117 * makes the internal stretch forces stronger, and hence makes the cloth 00118 * harder to stretch. The bend force can be controlled independently in 00119 * u and v. Generally, stretch forces should be very, very strong, 00120 * and bend forces should be very weak. 00121 * 00122 * The damp parameter controls the strength of damping forces. A higher 00123 * damping value will make the cloth come to rest quicker, while a lower 00124 * value will allow it to oscillate back and forth before coming to rest. 00125 * 00126 * The b_u and b_v values allow the client to force stretch/compression 00127 * of the cloth. They're not very useful at present; they should really be 00128 * spatially varying to be useful. 00129 * 00130 * The g parameter is the constant for acceleration due to gravity, 00131 * by default 9.81 m/s^2. 00132 */ 00133 class Params 00134 { 00135 public: 00136 // ----- member functions ----- 00137 00138 // MSVC bug requires this to be inline 00139 // Maya values: .5, .35, .01 (unknown scaling...) 00140 inline Params() 00141 : _k_stretch( 5000.f ), 00142 _k_shear( 500.f ), 00143 _k_bend_u( .00001f ), 00144 _k_bend_v( .00001f ), 00145 _k_damp( .2f ), 00146 _k_drag( .1f ), 00147 _b_u( 1.f ), 00148 _b_v( 1.f ), 00149 _g( 9.81f ) 00150 { 00151 } 00152 00153 // ----- data members ----- 00154 // TODO: Maya has separate u/v control for this 00155 Float _k_stretch; 00156 Float _k_shear; 00157 Float _k_bend_u, _k_bend_v; 00158 Float _k_damp; 00159 //! Drag constant. 00160 //! Technically, this is 0.5 * C_D * rho, where rho is density of 00161 //! the medium and C_D is the drag coefficient. We combine this into 00162 //! a single constant for simplicity. 00163 Float _k_drag; 00164 //! Stretch constant 00165 // FIXME: should be spatially varying, via texture. 00166 Float _b_u,_b_v; 00167 //! Gravitational acceleration 00168 Float _g; 00169 }; 00170 00171 // ----- types and enumerations ----- 00172 00173 //! The individual classes of forces. 00174 enum ForceType { 00175 F_STRETCH, 00176 F_SHEAR, 00177 F_BEND, 00178 F_GRAVITY, 00179 F_DRAG, 00180 00181 NB_FORCES 00182 }; 00183 00184 // ----- member functions ----- 00185 00186 explicit SimSimulator( const GeMesh& initialMesh ); 00187 00188 const GeMesh& getMesh() const; 00189 const RCShdPtr<GeMesh>& getMeshPtr() const; 00190 00191 //! Rewind simulation time to zero, and return the mesh to its initial 00192 //! state. 00193 void rewind(); 00194 00195 //! Advance the simulation by one timestep. 00196 //! step() is equivalent to calling 00197 //! - preSubSteps() 00198 //! - repeated subStep() calls 00199 //! - postSubSteps() 00200 void step(); 00201 00202 //@{ 00203 //! Finer grained simulation control - allows the client more control over 00204 //! the computation. See step() for details. 00205 bool subStepsDone() const; 00206 void preSubSteps(); 00207 void subStep(); 00208 void postSubSteps(); 00209 //@} 00210 00211 //! Retrieve the current simulation time. 00212 BaTime::Instant getTime() const; 00213 00214 //@{ 00215 //! Mutator 00216 void setTimestep( Float ); 00217 void setParams( const Params& ); 00218 void setDensity( Float rho ); 00219 void setPCGTolerance( Float ); 00220 //@} 00221 00222 //@{ 00223 //! Accessor 00224 Float getTimestep() const; 00225 const Params& getParams() const; 00226 Float getDensity() const; 00227 Float getPCGTolerance() const; 00228 //@} 00229 00230 //! Remove all constraints on all vertices. 00231 void removeAllConstraints(); 00232 //! Constrain movement of the vertex to the plane defined by the given 00233 //! normal. 00234 void setPosConstraintPlane( GeMesh::VertexId, const GeVector& ); 00235 //! Constrain movement of the vertex to the given line. 00236 void setPosConstraintLine( GeMesh::VertexId, const GeVector& ); 00237 //! Completely constrain the vertex, allowing no movement. 00238 void setPosConstraintFull( GeMesh::VertexId ); 00239 00240 //! Force the vertex to move with the specified velocity. This overrides 00241 //! any position constraints. 00242 void setVelConstraint( GeMesh::VertexId, const GeVector& ); 00243 00244 //@{ 00245 //! Only exposed for debugging purposes. 00246 GeVector getVelocity( GeMesh::VertexId vid ) const; 00247 GeVector getForce( GeMesh::VertexId vid ) const; 00248 Float getEnergy( ForceType ) const; 00249 Float getTriEnergy( ForceType, GeMesh::FaceId ) const; 00250 // The final two will only work in debug builds. 00251 GeVector getForce( ForceType type, GeMesh::VertexId vid ) const; 00252 GeVector getDampingForce( ForceType type, GeMesh::VertexId vid ) const; 00253 00254 void setMesh( const GeMesh& ); 00255 //@} 00256 00257 private: 00258 00259 // ----- types and enumerations ----- 00260 00261 // FIXME: implement custom matrix classes for these some time, if it 00262 // helps the performance much. 00263 typedef SimMatrix Matrix; 00264 typedef SimMatrix SymMatrix; 00265 typedef SimMatrix TridiagMatrix; 00266 00267 // ----- classes ----- 00268 00269 class CommonVars; 00270 class StretchVars; 00271 class ShearVars; 00272 class BendVars; 00273 00274 //////////////////////////////////////////////////////////////////////////// 00275 /*! 00276 * \class ModPCGSolver freecloth/simulator/simSimulator.h 00277 * 00278 * Preconditioned modified conjugate gradient solver. Solves a linear 00279 * system Ax=b subject to constraints defined by S and z, as defined by 00280 * [BarWit98] in section 5.3. 00281 */ 00282 class ModPCGSolver 00283 { 00284 public: 00285 // ----- member functions ----- 00286 00287 ModPCGSolver(); 00288 void preStep(); 00289 void step(); 00290 bool done() const; 00291 const SimVector& result() const; 00292 00293 //! Specify the tolerance. 00294 void setTolerance( Float ); 00295 //! Access the tolerance 00296 Float getTolerance() const; 00297 00298 // ----- data members ----- 00299 00300 std::vector<GeMatrix3> _S; 00301 SimVector _z; 00302 00303 // Final Ax=b system 00304 SymMatrix _A; 00305 SimVector _b; 00306 00307 private: 00308 // ----- member functions ----- 00309 00310 void setupPreconditioner(); 00311 void setupCG(); 00312 SimVector filter( const SimVector& ) const; 00313 void filterInPlace( SimVector& ) const; 00314 00315 // ----- data members ----- 00316 00317 SimMatrix _P, _Pinv; 00318 bool _done; 00319 UInt32 _nbSteps; 00320 Float _tolerance; 00321 00322 SimVector _x, _r, _c; 00323 Float _delta0, _deltaNew; 00324 00325 // Temporaries within step() 00326 SimVector _q, _s; 00327 }; 00328 00329 00330 // ----- member functions ----- 00331 00332 //! Fill the mass matrix (_M) using the initial mesh's triangles areas 00333 //! and the density parameter, as per [BarWit98] section 2.2. 00334 void setupMass(); 00335 00336 //! Calculate values common to the stretch and shear conditions. 00337 void calcStretchShear( 00338 const GeMesh::FaceWrapper& face 00339 ); 00340 //! Calculate the stretch condition and its derivatives. 00341 void calcStretch( 00342 const GeMesh::FaceWrapper& face, 00343 const CommonVars &cv, 00344 const GePoint x[3], 00345 const GePoint tp[3], 00346 const GeVector v0[ 3 ] 00347 ); 00348 //! Calculate the shear condition and its derivatives. 00349 void calcShear( 00350 const GeMesh::FaceWrapper& face, 00351 const CommonVars &cv, 00352 const GePoint x[3], 00353 const GePoint tp[3], 00354 const GeVector v0[ 3 ] 00355 ); 00356 //! Calculate the bend condition and its derivatives. 00357 void calcBend( 00358 const GeMeshWingedEdge::HalfEdgeWrapper& edge 00359 ); 00360 00361 // ----- data members ----- 00362 00363 // FIXME: initial mesh should be RCShdPtr<const GeMesh> 00364 RCShdPtr<GeMesh> _initialMesh; 00365 RCShdPtr<GeMeshWingedEdge> _initialMeshWingedEdge; 00366 RCShdPtr<GeMesh> _mesh; 00367 00368 Params _params; 00369 //! Density of cloth ( kg / m^2 ) 00370 Float _rho; 00371 //! Timestep 00372 Float _h; 00373 //! Current time 00374 Float _time; 00375 00376 00377 //! Variables from the [BarWit98], as defined in equations (6) and (14) 00378 TridiagMatrix _M; 00379 //! Sum of diagonals of _M 00380 Float _totalMass; 00381 SimVector _f0; 00382 SymMatrix _df_dx; 00383 SymMatrix _df_dv; 00384 SimVector _v0; 00385 SimVector _z0; 00386 00387 //@{ 00388 //! For debugging 00389 SimVector _f0i[ NB_FORCES ]; 00390 SimVector _d0i[ NB_FORCES ]; 00391 SymMatrix _df_dxi[ NB_FORCES ]; 00392 // df_dv is always zero... 00393 // Damping forces from the [BarWit98], as defined in section 4.5 00394 SymMatrix _dd_dvi[ NB_FORCES ]; 00395 SymMatrix _dd_dxi[ NB_FORCES ]; 00396 //@} 00397 00398 //@{ 00399 //! Total energy of cloth 00400 Float _fenergy[ NB_FORCES ]; 00401 Float _venergy; 00402 Float _energy; 00403 std::vector<Float> _trienergy[ NB_FORCES ]; 00404 //@} 00405 00406 ModPCGSolver _modPCG; 00407 }; 00408 00409 FREECLOTH_NAMESPACE_END 00410 00411 #endif