29 #include "../../idlib/precompiled.h"
32 #include "../Game_local.h"
43 static int lastTimerReset = 0;
44 static int numRigidBodies = 0;
45 static idTimer timer_total, timer_collision;
58 struct rigidBodyDerivatives_s {
63 } *d = (
struct rigidBodyDerivatives_s *) derivatives;
65 idMat3 inverseWorldInertiaTensor;
115 idVec3 r, linearVelocity, angularVelocity, velocity;
116 idMat3 inverseWorldInertiaTensor;
117 float impulseNumerator, impulseDenominator, vel;
131 velocity = linearVelocity + angularVelocity.
Cross(r);
136 vel = velocity * collision.
c.
normal;
142 impulseNumerator = -( 1.0f +
bouncyness ) * vel;
148 impulse = (impulseNumerator / impulseDenominator) * collision.
c.
normal;
155 if ( collision.
fraction < 0.0001f ) {
161 return self->Collide( collision, velocity );
176 bool collided =
false;
178 #ifdef TEST_COLLISION_DETECTION
199 #ifdef TEST_COLLISION_DETECTION
219 float magnitude, impulseNumerator, impulseDenominator;
220 idMat3 inverseWorldInertiaTensor;
221 idVec3 linearVelocity, angularVelocity;
222 idVec3 massCenter,
r, velocity, normal, impulse, normalVelocity;
235 velocity = linearVelocity + angularVelocity.
Cross(r);
241 normal = -( velocity - normalVelocity );
244 impulseDenominator =
inverseMass + ( ( inverseWorldInertiaTensor * r.
Cross( normal ) ).Cross( r ) * normal );
245 impulse = (impulseNumerator / impulseDenominator) * normal;
252 if ( normalVelocity *
contacts[i].normal < 0.0f ) {
254 normal = -normalVelocity;
256 impulseDenominator =
inverseMass + ( ( inverseWorldInertiaTensor * r.
Cross( normal ) ).Cross( r ) * normal );
257 impulse = (impulseNumerator / impulseDenominator) * normal;
278 idMat3 inverseWorldInertiaTensor;
304 contactWinding.
Clear();
321 if ( !contactWinding.
PointInside( gravityNormal, point, 0 ) ) {
394 gameLocal.
Warning(
"rigid body outside world bounds for entity '%s' type '%s' at (%s)",
419 I[0].
x, I[0].
y, I[0].
z,
420 I[1].x, I[1].y, I[1].z,
421 I[2].x, I[2].y, I[2].z ),
597 #define MAX_INERTIA_SCALE 10.0f
619 gameLocal.
Warning(
"idPhysics_RigidBody::SetClipModel: invalid mass for entity '%s' type '%s'",
634 gameLocal.
DWarning(
"idPhysics_RigidBody::SetClipModel: unbalanced inertia tensor for entity '%s' type '%s'",
637 inertiaScale[(minIndex+1)%3][(minIndex+1)%3] = min /
inertiaTensor[(minIndex+1)%3][(minIndex+1)%3];
638 inertiaScale[(minIndex+2)%3][(minIndex+2)%3] = min /
inertiaTensor[(minIndex+2)%3][(minIndex+2)%3];
695 if ( linear < 0.0f || linear > 1.0f ||
696 angular < 0.0f || angular > 1.0f ||
697 contact < 0.0f || contact > 1.0f ) {
838 idVec3 oldOrigin, masterOrigin;
839 idMat3 oldAxis, masterAxis;
841 bool collided, cameToRest =
false;
843 timeStep =
MS2SEC( timeStepMSec );
849 self->GetMasterPosition( masterOrigin, masterAxis );
896 timer_collision.
Start();
903 timer_collision.
Stop();
924 timer_collision.
Start();
930 timer_collision.
Stop();
951 if ( ent && ( !cameToRest || !ent->
IsAtRest() ) ) {
967 gameLocal.
Warning(
"rigid body moved outside world bounds for entity '%s' type '%s' at (%s)",
983 if ( endTimeMSec > lastTimerReset ) {
989 if ( endTimeMSec > lastTimerReset ) {
990 lastTimerReset = endTimeMSec;
993 timer_collision.
Clear();
1023 idVec3 linearVelocity, angularVelocity;
1024 idMat3 inverseWorldInertiaTensor;
1124 self->GetMasterPosition( masterOrigin, masterAxis );
1147 self->GetMasterPosition( masterOrigin, masterAxis );
1187 self->GetMasterPosition( masterOrigin, masterAxis );
1245 static idVec3 curLinearVelocity;
1247 return curLinearVelocity;
1256 static idVec3 curAngularVelocity;
1257 idMat3 inverseWorldInertiaTensor;
1261 return curAngularVelocity;
1420 self->GetMasterPosition( masterOrigin, masterAxis );
idCQuat ToCQuat(void) const
idPlayer * GetLocalPlayer() const
void SetAngularVelocity(const idVec3 &newAngularVelocity, int id=0)
void SetClipModel(idClipModel *model, float density, int id=0, bool freeOld=true)
int GetContents(void) const
void DrawVelocity(int id, float linearScale, float angularScale) const
void SetLinearVelocity(const idVec3 &newLinearVelocity, int id=0)
void ApplyImpulse(const int id, const idVec3 &point, const idVec3 &impulse)
idPhysics_RigidBody(void)
int GetRestStartTime(void) const
assert(prefInfo.fullscreenBtn)
ID_INLINE void TransposeMultiply(const idMat3 &transpose, const idMat3 &b, idMat3 &dst)
void Printf(const char *fmt,...) const id_attribute((format(printf
void SetContents(int newContents)
virtual float Evaluate(const float *state, float *newState, float t0, float t1)=0
void SetMaster(idEntity *master, const bool orientated)
int Contacts(contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity)
void AddToConvexHull(const idWinding *winding, const idVec3 &normal, const float epsilon=ON_EPSILON)
void SetNum(int newnum, bool resize=true)
idMat3 Transpose(void) const
const idBounds & GetBounds(int id=-1) const
bool TestIfAtRest(void) const
bool IsOutsideWorld(void) const
void AddForce(const int id, const idVec3 &point, const idVec3 &force)
const idMat3 & GetAxis(void) const
const idVec3 & GetAngularVelocity(int id=0) const
void SetPushed(int deltaTime)
rigidBodyPState_t current
const int RB_VELOCITY_MANTISSA_BITS
bool CollisionImpulse(const trace_t &collision, idVec3 &impulse)
void Save(idSaveGame *savefile) const
const idVec3 & SubVec3(int index) const
void void void void DWarning(const char *fmt,...) const id_attribute((format(printf
void idPhysics_RigidBody_RestorePState(idRestoreGame *savefile, rigidBodyPState_t &state)
void ReadBool(bool &value)
void ClipRotation(trace_t &results, const idRotation &rotation, const idClipModel *model) const
const idVec3 & GetOrigin(int id=0) const
const int RB_MOMENTUM_MANTISSA_BITS
const idVec3 & GetOrigin(void) const
bool IsPushable(void) const
void ReadFromSnapshot(const idBitMsgDelta &msg)
const int RB_FORCE_MANTISSA_BITS
virtual void ApplyImpulse(idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse)
double Milliseconds(void) const
idVec3 Cross(const idVec3 &a) const
virtual void DrawModel(cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis, const idVec3 &viewOrigin, const float radius)=0
friend void RigidBodyDerivatives(const float t, const void *clientData, const float *state, float *derivatives)
void RigidBodyDerivatives(const float t, const void *clientData, const float *state, float *derivatives)
const int RB_VELOCITY_EXPONENT_BITS
void WriteClipModel(const class idClipModel *clipModel)
void WriteVec3(const idVec3 &vec)
const float RB_VELOCITY_MAX
void ReadVec6(idVec6 &vec)
idCVar rb_showBodies("rb_showBodies","0", CVAR_GAME|CVAR_BOOL,"show rigid bodies")
virtual bool IsAtRest(void) const
const int RB_MOMENTUM_EXPONENT_BITS
void WriteBool(const bool value)
idCVar rb_showTimings("rb_showTimings","0", CVAR_GAME|CVAR_BOOL,"show rigid body cpu usage")
void void void Warning(const char *fmt,...) const id_attribute((format(printf
void GetImpactInfo(const int id, const idVec3 &point, impactInfo_t *info) const
float GetAngle(void) const
bool EvaluateContacts(void)
int GetContents(int id=-1) const
void GetMassProperties(const float density, float &mass, idVec3 ¢erOfMass, idMat3 &inertiaTensor) const
int GetNumPoints(void) const
void ReadFloat(float &value)
void WriteDeltaFloat(float oldValue, float newValue)
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
int ClipContents(const idClipModel *model) const
idMat3 inverseInertiaTensor
void WriteToSnapshot(idBitMsgDelta &msg) const
const idVec3 & GetLinearVelocity(int id=0) const
virtual void GetImpactInfo(idEntity *ent, int id, const idVec3 &point, impactInfo_t *info)
void WriteFloat(const float value)
cmHandle_t Handle(void) const
const idBounds & GetAbsBounds(int id=-1) const
const idVec3 & GetPushedAngularVelocity(const int id=0) const
const idBounds & GetBounds(void) const
bool IsAtRest(void) const
void WriteVec6(const idVec6 &vec)
idCVar rb_showInertia("rb_showInertia","0", CVAR_GAME|CVAR_BOOL,"show the inertia tensor of each rigid body")
bool IsTraceModel(void) const
void idPhysics_RigidBody_SavePState(idSaveGame *savefile, const rigidBodyPState_t &state)
const idVec3 & GetPushedLinearVelocity(const int id=0) const
const int RB_VELOCITY_TOTAL_BITS
float ReadDeltaFloat(float oldValue) const
void SetFriction(const float linear, const float angular, const float contact)
virtual void DrawText(const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align=1, const int lifetime=0, bool depthTest=false)=0
const int RB_FORCE_EXPONENT_BITS
float LengthSqr(void) const
void UpdateTime(int endTimeMSec)
static int BitsForInteger(int i)
idMat3 & OrthoNormalizeSelf(void)
void SetAxis(const idMat3 &newAxis, int id=-1)
float GetMass(int id=-1) const
const char * ToString(int precision=2) const
void WriteInt(const int value)
void WriteMat3(const idMat3 &mat)
bool CheckForCollisions(const float deltaTime, rigidBodyPState_t &next, trace_t &collision)
idList< contactInfo_t > contacts
const idVec3 & GetVec(void) const
void ReadMat3(idMat3 &mat)
idEntity * entities[MAX_GENTITIES]
ID_INLINE int Min3Index(T x, T y, T z)
void SetContents(int contents, int id=-1)
~idPhysics_RigidBody(void)
void AddContactEntitiesForContacts(void)
void ReadClipModel(idClipModel *&clipModel)
GLdouble GLdouble GLdouble r
END_CLASS const float STOP_SPEED
void SetClipMask(int mask, int id=-1)
const int RB_MOMENTUM_TOTAL_BITS
idCVar rb_showMass("rb_showMass","0", CVAR_GAME|CVAR_BOOL,"show the mass of each rigid body")
void SetOrigin(const idVec3 &rotationOrigin)
void Rotate(const idRotation &rotation, int id=-1)
idMat3 ToMat3(void) const
const idMat3 & ToMat3(void) const
bool PointInside(const idVec3 &normal, const idVec3 &point, const float epsilon) const
idMat3 ToMat3(void) const
void ContactFriction(float deltaTime)
bool Rotation(trace_t &results, const idVec3 &start, const idRotation &rotation, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity)
int GetNumClipModels(void) const
int Contents(const idVec3 &start, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity)
void RotationModel(trace_t &results, const idVec3 &start, const idRotation &rotation, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
int ContentsModel(const idVec3 &start, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
#define CLASS_DECLARATION(nameofsuperclass, nameofclass)
void Integrate(const float deltaTime, rigidBodyPState_t &next)
void ReadVec3(idVec3 &vec)
const char * c_str(void) const
idRotation ToRotation(void) const
void TranslationModel(trace_t &results, const idVec3 &start, const idVec3 &end, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
void Translate(const idVec3 &translation, int id=-1)
const int RB_FORCE_TOTAL_BITS
const idBounds & GetAbsBounds(void) const
float ReadFloat(void) const
void Restore(idRestoreGame *savefile)
ID_INLINE idMat3 SkewSymmetric(idVec3 const &src)
void ClipTranslation(trace_t &results, const idVec3 &translation, const idClipModel *model) const
void ActivateContactEntities(void)
void DropToFloorAndRest(void)
idRenderWorld * gameRenderWorld
char * va(const char *fmt,...)
bool Translation(trace_t &results, const idVec3 &start, const idVec3 &end, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity)
idMat3 Inverse(void) const
#define MAX_INERTIA_SCALE
void SetBouncyness(const float b)
const float RB_MOMENTUM_MAX
idCVar rb_showVelocity("rb_showVelocity","0", CVAR_GAME|CVAR_BOOL,"show the velocity of each rigid body")
static const float M_MS2SEC
idCVar rb_showActive("rb_showActive","0", CVAR_GAME|CVAR_BOOL,"show rigid bodies that are not at rest")
const idMat3 & GetAxis(int id=0) const
idClipModel * GetClipModel(int id=0) const
idCollisionModelManager * collisionModelManager
bool Motion(trace_t &results, const idVec3 &start, const idVec3 &end, const idRotation &rotation, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity)
void SetOrigin(const idVec3 &newOrigin, int id=-1)
static int BitsForFloat(float f)
bool Evaluate(int timeStepMSec, int endTimeMSec)
idMat3 & TransposeSelf(void)
void SetMass(float mass, int id=-1)