|
World of Rigid Bodies (WoRB)
|
00001 #ifndef _WORB_H_INCLUDED 00002 #define _WORB_H_INCLUDED 00003 00004 /** 00005 * @file WoRB.h 00006 * @brief The World of Rigid Bodies (WoRB) Simulation Framework. 00007 * @author Mikica B Kocic 00008 * @version 0.8 00009 * @date 2012-05-05 00010 * @copyright GNU Public License. 00011 */ 00012 00013 #include "RigidBody.h" 00014 #include "CollisionResolver.h" 00015 00016 namespace WoRB 00017 { 00018 /** Encapsulates a system of rigid bodies. 00019 */ 00020 template 00021 < 00022 /** The maximum number of rigid bodies the system can have. 00023 */ 00024 unsigned MaxObjects, 00025 00026 /** The maximum number of collisions the system can register. 00027 */ 00028 unsigned MaxCollisions 00029 > 00030 class WorldOfRigidBodies 00031 { 00032 /** Represents a rigid body iterator for the WorldOfRigidBodies class. 00033 * Iterates only through rigid bodies avoiding scenery geometries. 00034 */ 00035 class RigidBodies 00036 { 00037 WorldOfRigidBodies* worb; //!< Holds an instance where we iterate 00038 unsigned i; //!< The current geometry 00039 00040 public: 00041 00042 /** Constructs rigid body iterator for the given instance of WoRB. 00043 */ 00044 RigidBodies( WorldOfRigidBodies* worb ) 00045 : worb(worb), i(0) 00046 { 00047 while( i < worb->ObjectCount && worb->Object[i]->Body == 0 ) { 00048 ++i; 00049 } 00050 } 00051 00052 /** Advances to the next rigid body 00053 */ 00054 RigidBodies& operator++ () 00055 { 00056 i = Next( i + 1 ); 00057 return *this; 00058 } 00059 00060 /** Returns true if the current geometry is connected to a rigid body 00061 */ 00062 bool Exists () 00063 { 00064 return i < worb->ObjectCount && worb->Object[i]->Body != 0; 00065 } 00066 00067 /** Locates next rigid body from the given location 00068 */ 00069 unsigned Next( unsigned index ) 00070 { 00071 while( index < worb->ObjectCount && worb->Object[index]->Body == 0 ) { 00072 ++index; 00073 } 00074 return index; 00075 } 00076 00077 /** Gets the pointer to the current rigid body. 00078 */ 00079 RigidBody* operator -> () 00080 { 00081 return i < worb->ObjectCount ? worb->Object[i]->Body : 0; 00082 } 00083 00084 /** Removes all objects from the WoRB instance. 00085 */ 00086 void Clear () 00087 { 00088 worb->ObjectCount = 0; 00089 i = 0; 00090 } 00091 00092 /** Removes all objects from the WoRB instance. 00093 */ 00094 unsigned Count () 00095 { 00096 return worb->ObjectCount; 00097 } 00098 }; 00099 00100 ///////////////////////////////////////////////////////////////////////////////// 00101 00102 friend class RigidBodies; 00103 00104 /** Holds the number of the objects in the system. 00105 */ 00106 unsigned ObjectCount; 00107 00108 /** Points to an array of the objects handled by the system. 00109 */ 00110 Geometry* Object[ MaxObjects ]; 00111 00112 public: 00113 00114 ///////////////////////////////////////////////////////////////////////////////// 00115 00116 /** Holds common gravity applied to all objects (set to 0 to disable). 00117 */ 00118 Quaternion Gravity; 00119 00120 ///////////////////////////////////////////////////////////////////////////////// 00121 00122 /** Holds the system local time, in `s`. 00123 */ 00124 double Time; 00125 00126 /** Holds the number of integrator time-steps, from the simulation start. 00127 */ 00128 unsigned long TimeStepCount; 00129 00130 /** Holds the total kinetic energy of the system, in `J`. 00131 */ 00132 double TotalKineticEnergy; 00133 00134 /** Holds the total potential energy of the system, in `J`. 00135 */ 00136 double TotalPotentialEnergy; 00137 00138 /** Holds the total linear momentum of the system, in `kg m^2 s^-1`. 00139 */ 00140 Quaternion TotalLinearMomentum; 00141 00142 /** Holds the total angular momentum of the system, in `kg m^2 s^-1`. 00143 */ 00144 Quaternion TotalAngularMomentum; 00145 00146 ///////////////////////////////////////////////////////////////////////////////// 00147 00148 /** Holds the collision data for all registered collisions. 00149 */ 00150 CollisionResolver Collisions; 00151 00152 /** Holds the memory parcel where collisions are registered. 00153 */ 00154 Collision CollisionRegistry[ MaxCollisions ]; 00155 00156 ///////////////////////////////////////////////////////////////////////////////// 00157 00158 /** Constructs an instance of WoRB class. 00159 */ 00160 WorldOfRigidBodies () 00161 : Collisions( CollisionRegistry, MaxCollisions ) 00162 { 00163 } 00164 00165 ///////////////////////////////////////////////////////////////////////////////// 00166 00167 /** Removes all objects from the system. 00168 */ 00169 void RemoveObjects () 00170 { 00171 ObjectCount = 0; 00172 } 00173 00174 /** Adds new object to the system. 00175 */ 00176 void Add( Geometry* object ) 00177 { 00178 Object[ ObjectCount++ ] = object; 00179 } 00180 00181 /** Adds new object to the system. 00182 */ 00183 void Add( Geometry& object ) 00184 { 00185 Object[ ObjectCount++ ] = &object; 00186 } 00187 00188 ///////////////////////////////////////////////////////////////////////////////// 00189 00190 /** Prepares ODE (recalculates derived quantities) 00191 */ 00192 void InitializeODE () 00193 { 00194 Time = 0; 00195 TimeStepCount = 0; 00196 00197 Collisions.Initialize (); 00198 00199 for ( RigidBodies body = RigidBodies(this); body.Exists(); ++body ) 00200 { 00201 body->CalculateDerivedQuantities (); 00202 body->ClearAccumulators (); 00203 } 00204 00205 TotalKineticEnergy = 0; 00206 TotalPotentialEnergy = 0; 00207 TotalLinearMomentum = 0; 00208 TotalAngularMomentum = 0; 00209 00210 for ( RigidBodies body = RigidBodies(this); body.Exists(); ++body ) 00211 { 00212 TotalKineticEnergy += body->KineticEnergy; 00213 TotalPotentialEnergy += body->PotentialEnergy; 00214 TotalLinearMomentum += body->LinearMomentum; 00215 TotalAngularMomentum += body->TotalAngularMomentum; 00216 } 00217 } 00218 00219 /** Solves (integrates) equations of motion for the whole system 00220 * 00221 * Solves ODE for all the objects in the system, performs the contact generation 00222 * and then resolves detected contacts. 00223 */ 00224 void SolveODE( 00225 double h //!< Integrator time-step length 00226 ) 00227 { 00228 ///////////////////////////////////////////////////////////////////////////// 00229 // Calculate and accumulate all external and internal forces 00230 // 00231 00232 // Add gravity 00233 // 00234 for ( RigidBodies body = RigidBodies(this); body.Exists(); ++body ) 00235 { 00236 Quaternion f_g = body->Mass() * Gravity; 00237 double E_p = - f_g.Dot( body->Position ); 00238 00239 body->AddExternalForce( f_g, E_p ); 00240 } 00241 00242 ///////////////////////////////////////////////////////////////////////////// 00243 // Solve ODE for every object in the system 00244 // 00245 for ( RigidBodies body = RigidBodies(this); body.Exists(); ++body ) 00246 { 00247 body->SolveODE( h ); 00248 } 00249 00250 // Solve system local time (avoiding `Time += h` cause of rounding-errors). 00251 // 00252 Time = h * (++TimeStepCount); 00253 00254 ///////////////////////////////////////////////////////////////////////////// 00255 // Calculate derived quantities 00256 00257 TotalKineticEnergy = 0; 00258 TotalPotentialEnergy = 0; 00259 TotalLinearMomentum = 0; 00260 TotalAngularMomentum = 0; 00261 00262 for ( RigidBodies body = RigidBodies(this); body.Exists(); ++body ) 00263 { 00264 TotalKineticEnergy += body->KineticEnergy; 00265 TotalPotentialEnergy += body->PotentialEnergy; 00266 TotalLinearMomentum += body->LinearMomentum; 00267 TotalAngularMomentum += body->TotalAngularMomentum; 00268 } 00269 00270 ///////////////////////////////////////////////////////////////////////////// 00271 // Collision Detection 00272 00273 Collisions.Initialize (); 00274 00275 // Detect and register collisions between all objects in the system 00276 // 00277 for ( unsigned i = 0; i < ObjectCount; ++i ) 00278 { 00279 for ( unsigned j = i + 1; j < ObjectCount; ++j ) 00280 { 00281 Object[i]->Detect( Collisions, Object[j] ); 00282 } 00283 } 00284 00285 Collisions.UpdateDerivedQuantities( h ); 00286 00287 ///////////////////////////////////////////////////////////////////////////// 00288 // Collision Response 00289 00290 Collisions.ImpulseTransfers( h ); 00291 Collisions.PositionProjections (); 00292 00293 ///////////////////////////////////////////////////////////////////////////// 00294 // Prepare force and torque accumulators for the next time-step 00295 // 00296 for ( RigidBodies body = RigidBodies(this); body.Exists(); ++body ) 00297 { 00298 body->ClearAccumulators (); 00299 } 00300 } 00301 }; 00302 00303 /** User defined ANSI C printf-style output routine. 00304 */ 00305 void Printf( const char* format, ... ); 00306 00307 /** Reports a severe error (with errorId compatible with MATLAB) and quits. 00308 */ 00309 void SevereError( const char* errorId, const char* format, ... ); 00310 } 00311 00312 /** 00313 * @mainpage World of (Rigid) Bodies Simulation Framework 00314 * 00315 * World of Bodies (WoRB) is a system for real-time simulation of rigid bodies. 00316 * 00317 * @section use How to use WoRB framework 00318 * 00319 * Initialization 00320 * 00321 * @li Create a set of instances of Geometry and RigidBody 00322 * @li Set mass and inertia tensor for the rigid bodies 00323 * @li Set their initial location, orientation, velocity and angular velocity 00324 * @li Apply any permanent external forces, e.g. gravity 00325 * 00326 * @li Create an instance of WorldOfRigidBodies 00327 * @li Populate WorldOfRigidBodies::Objects with the list of instantiated rigid bodies 00328 * 00329 * The main loop of the simulation 00330 * 00331 * @li Apply any temporary internal or external forces, e.g. spring forces or thrusts. 00332 * @li Call WorldOfRigidBodies::SolveODE 00333 * @li Render the bodies. 00334 * 00335 * The single step of the simulation is in WorldOfRigidBodies::SolveODE, which 00336 * performs the following steps 00337 * 00338 * @li Solve ODE on each body in the system 00339 * @li Collision detection: find all collisions between all geometries 00340 * @li Collision response: resolve all the collisions 00341 * @li Update the internal derived quantities of the rigid bodies and geometries 00342 */ 00343 00344 #endif // _WORB_H_INCLUDED