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 * References: 00089 * - [BarWit98] D. Baraff and A. Witkin. Large Steps in Cloth Simulation. 00090 * SIGGRAPH Conference Proceedings, 1998, 43-54. 00091 * http://www-2.cs.cmu.edu/~baraff/papers/sig98.pdf 00092 * - [Pri02] D. Pritchard. "Implementing Baraff & Witkin's Cloth Simulation". 00093 * Unpublished, 2002. 00094 * http://freecloth.enigmati.ca/docs/report-chaps/ 00095 * - [Mac00] D. Macri. Real-Time Cloth. Game Developers Conference, 2000. 00096 * http://www.gdconf.com/archives/2000/macri.doc 00097 */ 00098 00099 // FIXME: the mesh should be allowed to have cylindrical or spherical 00100 // topology, not just disc topology. 00101 // 00102 // FIXME: should really implement this as a Bridge pattern, to hide the 00103 // implementation from clients better. 00104 class SimSimulator : public RCBase 00105 { 00106 public: 00107 // ----- classes ----- 00108 //////////////////////////////////////////////////////////////////////////// 00109 /*! 00110 * \class Params freecloth/simulator/simSimulator.h 00111 * \brief Parameters for cloth simulator, as described in [BarWit98]. 00112 * 00113 * The stretch, shear, and bend parameters control the strength of the 00114 * associated internal forces. For example, a higher _k_stretch value 00115 * makes the internal stretch forces stronger, and hence makes the cloth 00116 * harder to stretch. The bend force can be controlled independently in 00117 * u and v. Generally, stretch forces should be very, very strong, 00118 * and bend forces should be very weak. 00119 * 00120 * The damp parameter controls the strength of damping forces. A higher 00121 * damping value will make the cloth come to rest quicker, while a lower 00122 * value will allow it to oscillate back and forth before coming to rest. 00123 * 00124 * The b_u and b_v values allow the client to force stretch/compression 00125 * of the cloth. They're not very useful at present; they should really be 00126 * spatially varying to be useful. 00127 * 00128 * The g parameter is the constant for acceleration due to gravity, 00129 * by default 9.81 m/s^2. 00130 */ 00131 class Params 00132 { 00133 public: 00134 // ----- member functions ----- 00135 00136 // MSVC bug requires this to be inline 00137 // Maya values: .5, .35, .01 (unknown scaling...) 00138 inline Params() 00139 : _k_stretch( 5000.f ), 00140 _k_shear( 500.f ), 00141 _k_bend_u( .00001f ), 00142 _k_bend_v( .00001f ), 00143 _k_damp( .2f ), 00144 _k_drag( .1f ), 00145 _b_u( 1.f ), 00146 _b_v( 1.f ), 00147 _g( 9.81f ) 00148 { 00149 } 00150 00151 // ----- data members ----- 00152 // TODO: Maya has separate u/v control for this 00153 Float _k_stretch; 00154 Float _k_shear; 00155 Float _k_bend_u, _k_bend_v; 00156 Float _k_damp; 00157 //! Drag constant. 00158 //! Technically, this is 0.5 * C_D * rho, where rho is density of 00159 //! the medium and C_D is the drag coefficient. We combine this into 00160 //! a single constant for simplicity. 00161 Float _k_drag; 00162 //! Stretch constant 00163 // FIXME: should be spatially varying, via texture. 00164 Float _b_u,_b_v; 00165 //! Gravitational acceleration 00166 Float _g; 00167 }; 00168 00169 // ----- types and enumerations ----- 00170 00171 //! The individual classes of forces. 00172 enum ForceType { 00173 F_STRETCH, 00174 F_SHEAR, 00175 F_BEND, 00176 F_GRAVITY, 00177 F_DRAG, 00178 00179 NB_FORCES 00180 }; 00181 00182 // ----- member functions ----- 00183 00184 explicit SimSimulator( const GeMesh& initialMesh ); 00185 00186 const GeMesh& getMesh() const; 00187 const RCShdPtr<GeMesh>& getMeshPtr() const; 00188 00189 //! Rewind simulation time to zero, and return the mesh to its initial 00190 //! state. 00191 void rewind(); 00192 00193 //! Advance the simulation by one timestep. 00194 //! step() is equivalent to calling 00195 //! - preSubSteps() 00196 //! - repeated subStep() calls 00197 //! - postSubSteps() 00198 void step(); 00199 00200 //@{ 00201 //! Finer grained simulation control - allows the client more control over 00202 //! the computation. See step() for details. 00203 bool subStepsDone() const; 00204 void preSubSteps(); 00205 void subStep(); 00206 void postSubSteps(); 00207 //@} 00208 00209 //! Retrieve the current simulation time. 00210 BaTime::Instant getTime() const; 00211 00212 //@{ 00213 //! Mutator 00214 void setTimestep( Float ); 00215 void setParams( const Params& ); 00216 void setDensity( Float rho ); 00217 void setPCGTolerance( Float ); 00218 //@} 00219 00220 //@{ 00221 //! Accessor 00222 Float getTimestep() const; 00223 const Params& getParams() const; 00224 Float getDensity() const; 00225 Float getPCGTolerance() const; 00226 //@} 00227 00228 //! Remove all constraints on all vertices. 00229 void removeAllConstraints(); 00230 //! Constrain movement of the vertex to the plane defined by the given 00231 //! normal. 00232 void setPosConstraintPlane( GeMesh::VertexId, const GeVector& ); 00233 //! Constrain movement of the vertex to the given line. 00234 void setPosConstraintLine( GeMesh::VertexId, const GeVector& ); 00235 //! Completely constrain the vertex, allowing no movement. 00236 void setPosConstraintFull( GeMesh::VertexId ); 00237 00238 //! Force the vertex to move with the specified velocity. This overrides 00239 //! any position constraints. 00240 void setVelConstraint( GeMesh::VertexId, const GeVector& ); 00241 00242 //@{ 00243 //! Only exposed for debugging purposes. 00244 GeVector getVelocity( GeMesh::VertexId vid ) const; 00245 GeVector getForce( GeMesh::VertexId vid ) const; 00246 Float getEnergy( ForceType ) const; 00247 Float getTriEnergy( ForceType, GeMesh::FaceId ) const; 00248 // The final two will only work in debug builds. 00249 GeVector getForce( ForceType type, GeMesh::VertexId vid ) const; 00250 GeVector getDampingForce( ForceType type, GeMesh::VertexId vid ) const; 00251 00252 void setMesh( const GeMesh& ); 00253 //@} 00254 00255 private: 00256 00257 // ----- types and enumerations ----- 00258 00259 // FIXME: implement custom matrix classes for these some time, if it 00260 // helps the performance much. 00261 typedef SimMatrix Matrix; 00262 typedef SimMatrix SymMatrix; 00263 typedef SimMatrix TridiagMatrix; 00264 00265 // ----- classes ----- 00266 00267 class CommonVars; 00268 class StretchVars; 00269 class ShearVars; 00270 class BendVars; 00271 00272 //////////////////////////////////////////////////////////////////////////// 00273 /*! 00274 * \class ModPCGSolver freecloth/simulator/simSimulator.h 00275 * 00276 * Preconditioned modified conjugate gradient solver. Solves a linear 00277 * system Ax=b subject to constraints defined by S and z, as defined by 00278 * [BarWit98] in section 5.3. 00279 */ 00280 class ModPCGSolver 00281 { 00282 public: 00283 // ----- member functions ----- 00284 00285 ModPCGSolver(); 00286 void preStep(); 00287 void step(); 00288 bool done() const; 00289 const SimVector& result() const; 00290 00291 //! Specify the tolerance. 00292 void setTolerance( Float ); 00293 //! Access the tolerance 00294 Float getTolerance() const; 00295 00296 // ----- data members ----- 00297 00298 std::vector<GeMatrix3> _S; 00299 SimVector _z; 00300 00301 // Final Ax=b system 00302 SymMatrix _A; 00303 SimVector _b; 00304 00305 private: 00306 // ----- member functions ----- 00307 00308 void setupPreconditioner(); 00309 void setupCG(); 00310 SimVector filter( const SimVector& ) const; 00311 void filterInPlace( SimVector& ) const; 00312 00313 // ----- data members ----- 00314 00315 SimMatrix _P, _Pinv; 00316 bool _done; 00317 UInt32 _nbSteps; 00318 Float _tolerance; 00319 00320 SimVector _x, _r, _c; 00321 Float _delta0, _deltaNew; 00322 00323 // Temporaries within step() 00324 SimVector _q, _s; 00325 }; 00326 00327 00328 // ----- member functions ----- 00329 00330 //! Fill the mass matrix (_M) using the initial mesh's triangles areas 00331 //! and the density parameter, as per [BarWit98] section 2.2. 00332 void setupMass(); 00333 00334 //! Calculate values common to the stretch and shear conditions. 00335 void calcStretchShear( 00336 const GeMesh::FaceWrapper& face 00337 ); 00338 //! Calculate the stretch condition and its derivatives. 00339 void calcStretch( 00340 const GeMesh::FaceWrapper& face, 00341 const CommonVars &cv, 00342 const GePoint x[3], 00343 const GePoint tp[3], 00344 const GeVector v0[ 3 ] 00345 ); 00346 //! Calculate the shear condition and its derivatives. 00347 void calcShear( 00348 const GeMesh::FaceWrapper& face, 00349 const CommonVars &cv, 00350 const GePoint x[3], 00351 const GePoint tp[3], 00352 const GeVector v0[ 3 ] 00353 ); 00354 //! Calculate the bend condition and its derivatives. 00355 void calcBend( 00356 const GeMeshWingedEdge::HalfEdgeWrapper& edge 00357 ); 00358 00359 // ----- data members ----- 00360 00361 // FIXME: initial mesh should be RCShdPtr<const GeMesh> 00362 RCShdPtr<GeMesh> _initialMesh; 00363 RCShdPtr<GeMeshWingedEdge> _initialMeshWingedEdge; 00364 RCShdPtr<GeMesh> _mesh; 00365 00366 Params _params; 00367 //! Density of cloth ( kg / m^2 ) 00368 Float _rho; 00369 //! Timestep 00370 Float _h; 00371 //! Current time 00372 Float _time; 00373 00374 00375 //! Variables from the [BarWit98], as defined in equations (6) and (14) 00376 TridiagMatrix _M; 00377 //! Sum of diagonals of _M 00378 Float _totalMass; 00379 SimVector _f0; 00380 SymMatrix _df_dx; 00381 SymMatrix _df_dv; 00382 SimVector _v0; 00383 SimVector _z0; 00384 00385 //@{ 00386 //! For debugging 00387 SimVector _f0i[ NB_FORCES ]; 00388 SimVector _d0i[ NB_FORCES ]; 00389 SymMatrix _df_dxi[ NB_FORCES ]; 00390 // df_dv is always zero... 00391 // Damping forces from the [BarWit98], as defined in section 4.5 00392 SymMatrix _dd_dvi[ NB_FORCES ]; 00393 SymMatrix _dd_dxi[ NB_FORCES ]; 00394 //@} 00395 00396 //@{ 00397 //! Total energy of cloth 00398 Float _fenergy[ NB_FORCES ]; 00399 Float _venergy; 00400 Float _energy; 00401 std::vector<Float> _trienergy[ NB_FORCES ]; 00402 //@} 00403 00404 ModPCGSolver _modPCG; 00405 }; 00406 00407 FREECLOTH_NAMESPACE_END 00408 00409 #endif