|
World of Rigid Bodies (WoRB)
|
00001 #ifndef _WORB_COLLISION_RESOLVER_H_INCLUDED 00002 #define _WORB_COLLISION_RESOLVER_H_INCLUDED 00003 00004 /** 00005 * @file CollisionResolver.h 00006 * @brief Definitions for the CollisionResolver class which implements 00007 * collision response algorithms for the system of rigid bodies. 00008 * @author Mikica Kocic 00009 * @version 0.16 00010 * @date 2012-05-02 00011 * @copyright GNU Public License. 00012 */ 00013 00014 #include "Geometry.h" 00015 #include "Collision.h" 00016 00017 namespace WoRB 00018 { 00019 /** Encapsulates collision response framework. 00020 * 00021 * All collisions in the system, after detection, are registered in an 00022 * instance of the CollisionResolver class and then resolved using 00023 * the impulse transfer and the position projections methods. 00024 * 00025 * The CollisionResolver instance may be shared between different WoRB systems. 00026 */ 00027 class CollisionResolver 00028 { 00029 ///////////////////////////////////////////////////////////////////////////////// 00030 /** @name Private properties */ 00031 /*@{*/ 00032 /** Holds the maximum number of collisions the array can take. 00033 */ 00034 unsigned MaxCollisionCount; 00035 00036 /** Holds the parcel for the collision data. 00037 * Allocation of the parcel is left to the user (may be dynamic or static). 00038 */ 00039 Collision* Collisions; 00040 00041 /** Holds the next free place in the parcel. 00042 */ 00043 Collision* NextFree; 00044 00045 /** Holds the free space in allocation area. 00046 */ 00047 unsigned FreeCount; 00048 00049 /** Holds the current number of collisions found. 00050 */ 00051 unsigned CollisionCount; 00052 00053 public: 00054 /*@}*/ 00055 ///////////////////////////////////////////////////////////////////////////////// 00056 /** @name Public properties */ 00057 /*@{*/ 00058 /** Holds the restitution coefficient common for all collisions. 00059 */ 00060 double Restitution; 00061 00062 /** Holds the position projections coefficient common for all collisions. 00063 */ 00064 double Relaxation; 00065 00066 /** Holds the friction coefficient common for all collisions. 00067 */ 00068 double Friction; 00069 /*@}*/ 00070 ///////////////////////////////////////////////////////////////////////////////// 00071 /** @name Constructor */ 00072 /*@{*/ 00073 /** Instantiates a collision detection framework in the given area. 00074 */ 00075 CollisionResolver( Collision* allocationArea, unsigned length ) 00076 : MaxCollisionCount( length ) 00077 , Collisions( allocationArea ) 00078 , NextFree( allocationArea ) 00079 , FreeCount( length ) 00080 , CollisionCount( 0 ) 00081 , Restitution( 1.0 ) 00082 , Relaxation( 0.2 ) 00083 , Friction( 0.0 ) 00084 { 00085 } 00086 /*@}*/ 00087 ///////////////////////////////////////////////////////////////////////////////// 00088 /** @name Property getters and index operations */ 00089 /*@{*/ 00090 /** Gets number of contats in the registry. 00091 */ 00092 unsigned Count () const 00093 { 00094 return CollisionCount; 00095 } 00096 00097 /** Checks if there is a free space available for more contact data. 00098 */ 00099 bool HasSpaceForMoreContacts () const 00100 { 00101 return FreeCount > 0; 00102 } 00103 00104 /** Gets collision data with the specified index. 00105 */ 00106 const Collision& operator [] ( unsigned index ) const 00107 { 00108 return Collisions[ index ]; 00109 } 00110 /*@}*/ 00111 ///////////////////////////////////////////////////////////////////////////////// 00112 /** @name Collision detection methods */ 00113 /*@{*/ 00114 /** Clears the collision registry. 00115 */ 00116 void Initialize () 00117 { 00118 NextFree = Collisions; 00119 FreeCount = MaxCollisionCount; 00120 CollisionCount = 0; 00121 } 00122 00123 /** Registers a new contact. 00124 * @return 1 if ok, 0 if failed to allocate space for the contact. 00125 */ 00126 unsigned RegisterNewContact 00127 ( 00128 RigidBody* body_A, //!< The first body 00129 RigidBody* body_B, //!< The second body; 0 in case of scenery 00130 const Quaternion& position, //!< The position of the contact in world frame 00131 const Quaternion& normal, //!< The contact normal in world frame 00132 double penetration //!< The penetration depth 00133 ) 00134 { 00135 if ( FreeCount <= 0 ) { 00136 return 0; 00137 } 00138 00139 // Add contact the list of maintained collisions. 00140 // 00141 NextFree->Body_A = body_A; 00142 NextFree->Body_B = body_B; 00143 NextFree->Position = position; 00144 NextFree->Normal = normal; 00145 NextFree->Penetration = penetration; 00146 NextFree->Friction = Friction; 00147 NextFree->Restitution = Restitution; 00148 00149 // Reduce the number of remainging contacts and advance the array forward. 00150 // 00151 ++NextFree; --FreeCount; 00152 ++CollisionCount; 00153 00154 return 1; 00155 } 00156 00157 /** Updates drived quantities (like contact velocity and axis info). 00158 */ 00159 void UpdateDerivedQuantities( double timeStep ) 00160 { 00161 for ( unsigned i = 0; i < CollisionCount; ++i ) 00162 { 00163 Collisions[i].UpdateDerivedQuantities( timeStep ); 00164 } 00165 } 00166 /*@}*/ 00167 ///////////////////////////////////////////////////////////////////////////////// 00168 /** @name Collision response methods */ 00169 /*@{*/ 00170 /** Resolves collisions using the impulse transfer method. 00171 */ 00172 void ImpulseTransfers( double timeStep, 00173 unsigned maxIterations = 0, double velocityEPS = 0.01 ); 00174 00175 /** Resolves collisions using the position projection method. 00176 */ 00177 void PositionProjections( 00178 unsigned maxIterations = 0, double positionEPS = 0.01 ); 00179 /*@}*/ 00180 ///////////////////////////////////////////////////////////////////////////////// 00181 /** @name Miscellanous methods */ 00182 /*@{*/ 00183 /** Displays information about all registered collisions on standard output. 00184 */ 00185 public: void Dump( double currentTime ) const; 00186 00187 /** Find a collision with the maximum bouncing velocity. 00188 */ 00189 Collision* FindLargestBouncingVelocity( double eps ) 00190 { 00191 Collision* contact = 0; 00192 for ( unsigned i = 0; i < CollisionCount; i++ ) 00193 { 00194 if ( Collisions[i].BouncingVelocity > eps ) 00195 { 00196 eps = Collisions[i].BouncingVelocity; 00197 contact = &Collisions[i]; 00198 } 00199 } 00200 return contact; 00201 } 00202 00203 /** Finds a collision with the largest penetration. 00204 */ 00205 Collision* FindLargestPenetration( double eps ) 00206 { 00207 Collision* contact = 0; 00208 for ( unsigned i = 0; i < CollisionCount; ++i ) 00209 { 00210 if ( Collisions[i].Penetration > eps ) 00211 { 00212 eps = Collisions[i].Penetration; 00213 contact = &Collisions[i]; 00214 } 00215 } 00216 return contact; 00217 } 00218 /*@}*/ 00219 ///////////////////////////////////////////////////////////////////////////////// 00220 }; 00221 00222 } // namespace WoRB 00223 00224 #endif // _WORB_COLLISION_RESOLVER_H_INCLUDED