World of Rigid Bodies (WoRB)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
WoRB.h
Go to the documentation of this file.
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