mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-21 13:10:37 +02:00
Quake 4 integrated with DoomRTX
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,407 @@
|
||||
|
||||
#ifndef __CLIP_H__
|
||||
#define __CLIP_H__
|
||||
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: SD's clip sector code
|
||||
const int CLIPSECTOR_DEPTH = 6;
|
||||
const int CLIPSECTOR_WIDTH = 1 << CLIPSECTOR_DEPTH;
|
||||
// RAVEN END
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Handles collision detection with the world and between physics objects.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#define CLIPMODEL_ID_TO_JOINT_HANDLE( id ) ( ( id ) >= 0 ? INVALID_JOINT : ((jointHandle_t) ( -1 - id )) )
|
||||
#define JOINT_HANDLE_TO_CLIPMODEL_ID( id ) ( -1 - id )
|
||||
|
||||
class idClip;
|
||||
class idClipModel;
|
||||
class idEntity;
|
||||
|
||||
|
||||
//===============================================================
|
||||
//
|
||||
// idClipModel
|
||||
//
|
||||
//===============================================================
|
||||
|
||||
class idClipModel {
|
||||
|
||||
friend class idClip;
|
||||
|
||||
public:
|
||||
idClipModel( void );
|
||||
explicit idClipModel( const char *name );
|
||||
explicit idClipModel( const idTraceModel &trm, const idMaterial *material = NULL );
|
||||
explicit idClipModel( const int renderModelHandle );
|
||||
explicit idClipModel( const idClipModel *model );
|
||||
~idClipModel( void );
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: SD's clip sector code
|
||||
void UpdateDynamicContents( void );
|
||||
// RAVEN END
|
||||
|
||||
bool LoadModel( const char *name );
|
||||
void LoadModel( const idTraceModel &trm, const idMaterial *material, bool notHashed = false );
|
||||
void LoadModel( const int renderModelHandle );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
void Link( void ); // must have been linked with an entity and id before
|
||||
void Link( idEntity *ent, int newId, const idVec3 &newOrigin, const idMat3 &newAxis, int renderModelHandle = -1 );
|
||||
// RAVEN END
|
||||
void Unlink( void ); // unlink from sectors
|
||||
void SetPosition( const idVec3 &newOrigin, const idMat3 &newAxis ); // unlinks the clip model
|
||||
void Translate( const idVec3 &translation ); // unlinks the clip model
|
||||
void Rotate( const idRotation &rotation ); // unlinks the clip model
|
||||
void Enable( void ); // enable for clipping
|
||||
void Disable( void ); // keep linked but disable for clipping
|
||||
void SetContents( int newContents ); // override contents
|
||||
int GetContents( void ) const;
|
||||
void SetEntity( idEntity *newEntity );
|
||||
idEntity * GetEntity( void ) const;
|
||||
void SetId( int newId );
|
||||
int GetId( void ) const;
|
||||
void SetOwner( idEntity *newOwner );
|
||||
idEntity * GetOwner( void ) const;
|
||||
const idBounds & GetBounds( void ) const;
|
||||
const idBounds & GetAbsBounds( void ) const;
|
||||
const idVec3 & GetOrigin( void ) const;
|
||||
const idMat3 & GetAxis( void ) const;
|
||||
bool IsTraceModel( void ) const; // returns true if this is a trace model
|
||||
bool IsRenderModel( void ) const; // returns true if this is a render model
|
||||
bool IsLinked( void ) const; // returns true if the clip model is linked
|
||||
bool IsEnabled( void ) const; // returns true if enabled for collision detection
|
||||
bool IsEqual( const idTraceModel &trm ) const;
|
||||
idCollisionModel * GetCollisionModel( void ) const; // returns handle used to collide vs this model
|
||||
const idTraceModel * GetTraceModel( void ) const;
|
||||
void GetMassProperties( const float density, float &mass, idVec3 ¢erOfMass, idMat3 &inertiaTensor ) const;
|
||||
|
||||
static void ClearTraceModelCache( void );
|
||||
static int TraceModelCacheSize( void );
|
||||
static void SaveTraceModels( idSaveGame *savefile );
|
||||
static void RestoreTraceModels( idRestoreGame *savefile );
|
||||
|
||||
private:
|
||||
bool enabled; // true if this clip model is used for clipping
|
||||
// RAVEN BEGIN
|
||||
bool checked; // Splash's clip model code
|
||||
// RAVEN END
|
||||
idEntity * entity; // entity using this clip model
|
||||
int id; // id for entities that use multiple clip models
|
||||
idEntity * owner; // owner of the entity that owns this clip model
|
||||
idVec3 origin; // origin of clip model
|
||||
idMat3 axis; // orientation of clip model
|
||||
idBounds bounds; // bounds
|
||||
idBounds absBounds; // absolute bounds
|
||||
int contents; // all contents ored together
|
||||
idCollisionModel * collisionModel; // handle to collision model
|
||||
int traceModelIndex; // trace model used for collision detection
|
||||
int renderModelHandle; // render model def handle
|
||||
|
||||
struct clipLink_s * clipLinks; // links into sectors
|
||||
int touchCount;
|
||||
|
||||
void Init( void ); // initialize
|
||||
void FreeModel( void );
|
||||
void Link_r( struct clipSector_s *node );
|
||||
|
||||
static void CacheCollisionModels( void );
|
||||
static int AllocTraceModel( const idTraceModel &trm, const idMaterial *material, bool notHashed = false );
|
||||
static void ReplaceTraceModel( int index, const idTraceModel &trm, const idMaterial *material, bool notHashed = false );
|
||||
static void FreeTraceModel( int traceModelIndex );
|
||||
static int CopyTraceModel( const int traceModelIndex );
|
||||
static idTraceModel * GetCachedTraceModel( int traceModelIndex );
|
||||
static idCollisionModel*GetCachedCollisionModel( int traceModelIndex );
|
||||
static int GetTraceModelHashKey( const idTraceModel &trm );
|
||||
};
|
||||
|
||||
|
||||
ID_INLINE void idClipModel::Translate( const idVec3 &translation ) {
|
||||
Unlink();
|
||||
origin += translation;
|
||||
}
|
||||
|
||||
ID_INLINE void idClipModel::Rotate( const idRotation &rotation ) {
|
||||
Unlink();
|
||||
origin *= rotation;
|
||||
axis *= rotation.ToMat3();
|
||||
}
|
||||
|
||||
ID_INLINE void idClipModel::Enable( void ) {
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
ID_INLINE void idClipModel::Disable( void ) {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
ID_INLINE void idClipModel::SetContents( int newContents ) {
|
||||
contents = newContents;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: SD's clip sector code
|
||||
UpdateDynamicContents();
|
||||
// RAVEN END
|
||||
}
|
||||
|
||||
ID_INLINE int idClipModel::GetContents( void ) const {
|
||||
return contents;
|
||||
}
|
||||
|
||||
ID_INLINE void idClipModel::SetEntity( idEntity *newEntity ) {
|
||||
entity = newEntity;
|
||||
}
|
||||
|
||||
ID_INLINE idEntity *idClipModel::GetEntity( void ) const {
|
||||
return entity;
|
||||
}
|
||||
|
||||
ID_INLINE void idClipModel::SetId( int newId ) {
|
||||
id = newId;
|
||||
}
|
||||
|
||||
ID_INLINE int idClipModel::GetId( void ) const {
|
||||
return id;
|
||||
}
|
||||
|
||||
ID_INLINE void idClipModel::SetOwner( idEntity *newOwner ) {
|
||||
owner = newOwner;
|
||||
}
|
||||
|
||||
ID_INLINE idEntity *idClipModel::GetOwner( void ) const {
|
||||
return owner;
|
||||
}
|
||||
|
||||
ID_INLINE const idBounds &idClipModel::GetBounds( void ) const {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
ID_INLINE const idBounds &idClipModel::GetAbsBounds( void ) const {
|
||||
return absBounds;
|
||||
}
|
||||
|
||||
ID_INLINE const idVec3 &idClipModel::GetOrigin( void ) const {
|
||||
return origin;
|
||||
}
|
||||
|
||||
ID_INLINE const idMat3 &idClipModel::GetAxis( void ) const {
|
||||
return axis;
|
||||
}
|
||||
|
||||
ID_INLINE bool idClipModel::IsRenderModel( void ) const {
|
||||
return ( renderModelHandle != -1 );
|
||||
}
|
||||
|
||||
ID_INLINE bool idClipModel::IsTraceModel( void ) const {
|
||||
return ( traceModelIndex != -1 );
|
||||
}
|
||||
|
||||
ID_INLINE bool idClipModel::IsLinked( void ) const {
|
||||
return ( clipLinks != NULL );
|
||||
}
|
||||
|
||||
ID_INLINE bool idClipModel::IsEnabled( void ) const {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
ID_INLINE bool idClipModel::IsEqual( const idTraceModel &trm ) const {
|
||||
return ( traceModelIndex != -1 && *GetCachedTraceModel( traceModelIndex ) == trm );
|
||||
}
|
||||
|
||||
ID_INLINE const idTraceModel *idClipModel::GetTraceModel( void ) const {
|
||||
if ( !IsTraceModel() ) {
|
||||
return NULL;
|
||||
}
|
||||
return idClipModel::GetCachedTraceModel( traceModelIndex );
|
||||
}
|
||||
|
||||
|
||||
//===============================================================
|
||||
//
|
||||
// idClip
|
||||
//
|
||||
//===============================================================
|
||||
|
||||
class idClip {
|
||||
|
||||
friend class idClipModel;
|
||||
|
||||
public:
|
||||
idClip( void );
|
||||
|
||||
void Init( void );
|
||||
void Shutdown( void );
|
||||
|
||||
// clip versus the rest of the world
|
||||
// RAVEN BEGIN
|
||||
// nmckenzie: we have cases where both a guy and his target need to be ignored by a translation
|
||||
bool Translation( trace_t &results, const idVec3 &start, const idVec3 &end,
|
||||
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity, const idEntity *passEntity2 = 0 );
|
||||
// RAVEN END
|
||||
bool Rotation( trace_t &results, const idVec3 &start, const idRotation &rotation,
|
||||
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity );
|
||||
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 );
|
||||
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 );
|
||||
// RAVEN BEGIN
|
||||
// AReis: Added ability to get the entity that was touched as well.
|
||||
int Contents( const idVec3 &start,
|
||||
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity, idEntity **touchedEntity = NULL );
|
||||
// RAVEN END
|
||||
|
||||
// special case translations versus the rest of the world
|
||||
bool TracePoint( trace_t &results, const idVec3 &start, const idVec3 &end,
|
||||
int contentMask, const idEntity *passEntity );
|
||||
bool TraceBounds( trace_t &results, const idVec3 &start, const idVec3 &end, const idBounds &bounds,
|
||||
int contentMask, const idEntity *passEntity );
|
||||
|
||||
// clip versus a specific model
|
||||
void TranslationModel( trace_t &results, const idVec3 &start, const idVec3 &end,
|
||||
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask,
|
||||
idCollisionModel *model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
|
||||
void RotationModel( trace_t &results, const idVec3 &start, const idRotation &rotation,
|
||||
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask,
|
||||
idCollisionModel *model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
|
||||
int ContactsModel( contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth,
|
||||
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask,
|
||||
idCollisionModel *model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
|
||||
int ContentsModel( const idVec3 &start,
|
||||
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask,
|
||||
idCollisionModel *model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
|
||||
|
||||
// clip versus all entities but not the world
|
||||
// RAVEN BEGIN
|
||||
// nmckenzie: had to add a second pass entity so we can safely ignore both a guy and his target in some cases
|
||||
void TranslationEntities( trace_t &results, const idVec3 &start, const idVec3 &end,
|
||||
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity, const idEntity *passEntity2 = 0 );
|
||||
// RAVEN END
|
||||
|
||||
// get a contact feature
|
||||
bool GetModelContactFeature( const contactInfo_t &contact, const idClipModel *clipModel, idFixedWinding &winding ) const;
|
||||
|
||||
// get entities/clip models within or touching the given bounds
|
||||
int EntitiesTouchingBounds( const idBounds &bounds, int contentMask, idEntity **entityList, int maxCount ) const;
|
||||
int ClipModelsTouchingBounds( const idBounds &bounds, int contentMask, idClipModel **clipModelList, int maxCount ) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: another helper function, useful in MP
|
||||
int PlayersTouchingBounds( const idBounds &bounds, int contentMask, idPlayer **entityList, int maxCount ) const;
|
||||
// RAVEN END
|
||||
|
||||
const idBounds & GetWorldBounds( void ) const;
|
||||
idCollisionModel * GetWorldCollisionModel( void ) const { return world; }
|
||||
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: change to static
|
||||
static idClipModel * DefaultClipModel( void );
|
||||
static void FreeDefaultClipModel( void );
|
||||
// RAVEN END
|
||||
|
||||
// stats and debug drawing
|
||||
void PrintStatistics( void );
|
||||
void DrawClipModels( const idVec3 &eye, const float radius, const idEntity *passEntity, const idTypeInfo* type = NULL );
|
||||
bool DrawModelContactFeature( const contactInfo_t &contact, const idClipModel *clipModel, int lifetime ) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// rjohnson: added debug hud support
|
||||
void DebugHudStatistics( void );
|
||||
void ClearStatistics( void );
|
||||
// RAVEN END
|
||||
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: SD's clip sector code
|
||||
void CoordsForBounds( int* coords, idBounds& bounds ) const;
|
||||
void DrawClipSectors( void ) const;
|
||||
void DrawAreaClipSectors( float range ) const;
|
||||
static void UpdateDynamicContents( struct clipSector_s* sector );
|
||||
static void UpdateDynamicContents( idClipModel* clipModel );
|
||||
// RAVEN END
|
||||
|
||||
private:
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: SD's clip sector code
|
||||
idVec3 nodeScale;
|
||||
idVec3 nodeOffset;
|
||||
idVec3 nodeOffsetVisual;
|
||||
// ddynerman: change to static
|
||||
static idClipModel defaultClipModel;
|
||||
// RAVEN END
|
||||
struct clipSector_s * clipSectors;
|
||||
idCollisionModel * world;
|
||||
idBounds worldBounds;
|
||||
idClipModel temporaryClipModel;
|
||||
|
||||
mutable int touchCount;
|
||||
// statistics
|
||||
int numTranslations;
|
||||
int numRotations;
|
||||
int numMotions;
|
||||
int numRenderModelTraces;
|
||||
int numContents;
|
||||
int numContacts;
|
||||
|
||||
private:
|
||||
struct clipSector_s * CreateClipSectors_r( const int depth, const idBounds &bounds, idVec3 &maxSector );
|
||||
void ClipModelsTouchingBounds_r( const struct clipSector_s *node, struct listParms_s &parms ) const;
|
||||
const idTraceModel * TraceModelForClipModel( const idClipModel *mdl ) const;
|
||||
// RAVEN BEGIN
|
||||
// nmckenzie: had to add a second pass entity so we can safely ignore both a guy and his target in some cases
|
||||
int GetTraceClipModels( const idBounds &bounds, int contentMask, const idEntity *passEntity, idClipModel **clipModelList, const idEntity *passEntity2 = 0 ) const;
|
||||
// RAVEN END
|
||||
void TraceRenderModel( trace_t &trace, const idVec3 &start, const idVec3 &end, const float radius, const idMat3 &axis, idClipModel *touch ) const;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: SD's clip sector code
|
||||
void GetClipSectorsStaticContents( void );
|
||||
// RAVEN END
|
||||
};
|
||||
|
||||
|
||||
ID_INLINE bool idClip::TracePoint( trace_t &results, const idVec3 &start, const idVec3 &end, int contentMask, const idEntity *passEntity ) {
|
||||
Translation( results, start, end, NULL, mat3_identity, contentMask, passEntity );
|
||||
return ( results.fraction < 1.0f );
|
||||
}
|
||||
|
||||
ID_INLINE bool idClip::TraceBounds( trace_t &results, const idVec3 &start, const idVec3 &end, const idBounds &bounds, int contentMask, const idEntity *passEntity ) {
|
||||
temporaryClipModel.LoadModel( idTraceModel( bounds ), NULL, true );
|
||||
Translation( results, start, end, &temporaryClipModel, mat3_identity, contentMask, passEntity );
|
||||
return ( results.fraction < 1.0f );
|
||||
}
|
||||
|
||||
ID_INLINE const idBounds & idClip::GetWorldBounds( void ) const {
|
||||
return worldBounds;
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: SD's clip sector code
|
||||
ID_INLINE void idClip::CoordsForBounds( int* coords, idBounds& bounds ) const {
|
||||
float fCoords[ 4 ];
|
||||
|
||||
fCoords[ 0 ] = ( bounds[ 0 ].x - nodeOffset.x ) * nodeScale.x;
|
||||
fCoords[ 1 ] = ( bounds[ 0 ].y - nodeOffset.y ) * nodeScale.y;
|
||||
fCoords[ 2 ] = ( bounds[ 1 ].x - nodeOffset.x ) * nodeScale.x;
|
||||
fCoords[ 3 ] = ( bounds[ 1 ].y - nodeOffset.y ) * nodeScale.y;
|
||||
|
||||
int i;
|
||||
for( i = 0; i < 4; i++ ) {
|
||||
|
||||
coords[ i ] = idMath::FtoiFast( fCoords[ i ] );
|
||||
|
||||
if( coords[ i ] < 0 ) {
|
||||
coords[ i ] = 0;
|
||||
} else if( coords[ i ] > CLIPSECTOR_WIDTH - 1 ) {
|
||||
coords[ i ] = CLIPSECTOR_WIDTH - 1;
|
||||
}
|
||||
}
|
||||
coords[ 2 ]++; coords[ 3 ]++;
|
||||
}
|
||||
// RAVEN END
|
||||
|
||||
#endif /* !__CLIP_H__ */
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idClass, idForce )
|
||||
END_CLASS
|
||||
|
||||
idList<idForce*> idForce::forceList;
|
||||
|
||||
/*
|
||||
================
|
||||
idForce::idForce
|
||||
================
|
||||
*/
|
||||
idForce::idForce( void ) {
|
||||
forceList.Append( this );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce::~idForce
|
||||
================
|
||||
*/
|
||||
idForce::~idForce( void ) {
|
||||
forceList.Remove( this );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce::DeletePhysics
|
||||
================
|
||||
*/
|
||||
void idForce::DeletePhysics( const idPhysics *phys ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < forceList.Num(); i++ ) {
|
||||
forceList[i]->RemovePhysics( phys );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce::ClearForceList
|
||||
================
|
||||
*/
|
||||
void idForce::ClearForceList( void ) {
|
||||
forceList.Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce::Evaluate
|
||||
================
|
||||
*/
|
||||
void idForce::Evaluate( int time ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce::RemovePhysics
|
||||
================
|
||||
*/
|
||||
void idForce::RemovePhysics( const idPhysics *phys ) {
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
#ifndef __FORCE_H__
|
||||
#define __FORCE_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Force base class
|
||||
|
||||
A force object applies a force to a physics object.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idEntity;
|
||||
class idPhysics;
|
||||
|
||||
class idForce : public idClass {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idForce );
|
||||
|
||||
idForce( void );
|
||||
virtual ~idForce( void );
|
||||
static void DeletePhysics( const idPhysics *phys );
|
||||
static void ClearForceList( void );
|
||||
|
||||
public: // common force interface
|
||||
// evalulate the force up to the given time
|
||||
virtual void Evaluate( int time );
|
||||
// removes any pointers to the physics object
|
||||
virtual void RemovePhysics( const idPhysics *phys );
|
||||
|
||||
private:
|
||||
|
||||
static idList<idForce*> forceList;
|
||||
};
|
||||
|
||||
#endif /* !__FORCE_H__ */
|
||||
@@ -0,0 +1,109 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idForce, idForce_Constant )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::idForce_Constant
|
||||
================
|
||||
*/
|
||||
idForce_Constant::idForce_Constant( void ) {
|
||||
force = vec3_zero;
|
||||
physics = NULL;
|
||||
id = 0;
|
||||
point = vec3_zero;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::~idForce_Constant
|
||||
================
|
||||
*/
|
||||
idForce_Constant::~idForce_Constant( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::Save
|
||||
================
|
||||
*/
|
||||
void idForce_Constant::Save( idSaveGame *savefile ) const {
|
||||
savefile->WriteVec3( force );
|
||||
// TOSAVE: idPhysics * physics
|
||||
savefile->WriteInt( id );
|
||||
savefile->WriteVec3( point );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::Restore
|
||||
================
|
||||
*/
|
||||
void idForce_Constant::Restore( idRestoreGame *savefile ) {
|
||||
// Owner needs to call SetPhysics!!
|
||||
savefile->ReadVec3( force );
|
||||
savefile->ReadInt( id );
|
||||
savefile->ReadVec3( point );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::SetPosition
|
||||
================
|
||||
*/
|
||||
void idForce_Constant::SetPosition( idPhysics *physics, int id, const idVec3 &point ) {
|
||||
this->physics = physics;
|
||||
this->id = id;
|
||||
this->point = point;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::SetForce
|
||||
================
|
||||
*/
|
||||
void idForce_Constant::SetForce( const idVec3 &force ) {
|
||||
this->force = force;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::SetPhysics
|
||||
================
|
||||
*/
|
||||
void idForce_Constant::SetPhysics( idPhysics *physics ) {
|
||||
this->physics = physics;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::Evaluate
|
||||
================
|
||||
*/
|
||||
void idForce_Constant::Evaluate( int time ) {
|
||||
idVec3 p;
|
||||
|
||||
if ( !physics ) {
|
||||
return;
|
||||
}
|
||||
|
||||
p = physics->GetOrigin( id ) + point * physics->GetAxis( id );
|
||||
|
||||
physics->AddForce( id, p, force );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Constant::RemovePhysics
|
||||
================
|
||||
*/
|
||||
void idForce_Constant::RemovePhysics( const idPhysics *phys ) {
|
||||
if ( physics == phys ) {
|
||||
physics = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
#ifndef __FORCE_CONSTANT_H__
|
||||
#define __FORCE_CONSTANT_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Constant force
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idForce_Constant : public idForce {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idForce_Constant );
|
||||
|
||||
idForce_Constant( void );
|
||||
virtual ~idForce_Constant( void );
|
||||
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
// constant force
|
||||
void SetForce( const idVec3 &force );
|
||||
// set force position
|
||||
void SetPosition( idPhysics *physics, int id, const idVec3 &point );
|
||||
|
||||
void SetPhysics( idPhysics *physics );
|
||||
|
||||
public: // common force interface
|
||||
virtual void Evaluate( int time );
|
||||
virtual void RemovePhysics( const idPhysics *phys );
|
||||
|
||||
private:
|
||||
// force properties
|
||||
idVec3 force;
|
||||
idPhysics * physics;
|
||||
int id;
|
||||
idVec3 point;
|
||||
};
|
||||
|
||||
#endif /* !__FORCE_CONSTANT_H__ */
|
||||
@@ -0,0 +1,131 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idForce, idForce_Drag )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::idForce_Drag
|
||||
================
|
||||
*/
|
||||
idForce_Drag::idForce_Drag( void ) {
|
||||
damping = 0.5f;
|
||||
dragPosition = vec3_zero;
|
||||
physics = NULL;
|
||||
id = 0;
|
||||
p = vec3_zero;
|
||||
dragPosition = vec3_zero;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::~idForce_Drag
|
||||
================
|
||||
*/
|
||||
idForce_Drag::~idForce_Drag( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::Init
|
||||
================
|
||||
*/
|
||||
void idForce_Drag::Init( float damping ) {
|
||||
if ( damping >= 0.0f && damping < 1.0f ) {
|
||||
this->damping = damping;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::SetPhysics
|
||||
================
|
||||
*/
|
||||
void idForce_Drag::SetPhysics( idPhysics *phys, int id, const idVec3 &p ) {
|
||||
this->physics = phys;
|
||||
this->id = id;
|
||||
this->p = p;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::SetDragPosition
|
||||
================
|
||||
*/
|
||||
void idForce_Drag::SetDragPosition( const idVec3 &pos ) {
|
||||
this->dragPosition = pos;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::GetDragPosition
|
||||
================
|
||||
*/
|
||||
const idVec3 &idForce_Drag::GetDragPosition( void ) const {
|
||||
return this->dragPosition;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::GetDraggedPosition
|
||||
================
|
||||
*/
|
||||
const idVec3 idForce_Drag::GetDraggedPosition( void ) const {
|
||||
return ( physics->GetOrigin( id ) + p * physics->GetAxis( id ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::Evaluate
|
||||
================
|
||||
*/
|
||||
void idForce_Drag::Evaluate( int time ) {
|
||||
float l1, l2, mass;
|
||||
idVec3 dragOrigin, dir1, dir2, velocity, centerOfMass;
|
||||
idMat3 inertiaTensor;
|
||||
idRotation rotation;
|
||||
idClipModel *clipModel;
|
||||
|
||||
if ( !physics ) {
|
||||
return;
|
||||
}
|
||||
|
||||
clipModel = physics->GetClipModel( id );
|
||||
if ( clipModel != NULL && clipModel->IsTraceModel() ) {
|
||||
clipModel->GetMassProperties( 1.0f, mass, centerOfMass, inertiaTensor );
|
||||
} else {
|
||||
centerOfMass.Zero();
|
||||
}
|
||||
|
||||
centerOfMass = physics->GetOrigin( id ) + centerOfMass * physics->GetAxis( id );
|
||||
dragOrigin = physics->GetOrigin( id ) + p * physics->GetAxis( id );
|
||||
|
||||
dir1 = dragPosition - centerOfMass;
|
||||
dir2 = dragOrigin - centerOfMass;
|
||||
l1 = dir1.Normalize();
|
||||
l2 = dir2.Normalize();
|
||||
|
||||
rotation.Set( centerOfMass, dir2.Cross( dir1 ), RAD2DEG( idMath::ACos( dir1 * dir2 ) ) );
|
||||
physics->SetAngularVelocity( rotation.ToAngularVelocity() / MS2SEC( gameLocal.GetMSec() ), id );
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: use GetMSec access rather than USERCMD_TIME
|
||||
velocity = physics->GetLinearVelocity( id ) * damping + dir1 * ( ( l1 - l2 ) * ( 1.0f - damping ) / MS2SEC( gameLocal.GetMSec ( ) ) );
|
||||
// RAVEN END
|
||||
physics->SetLinearVelocity( velocity, id );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Drag::RemovePhysics
|
||||
================
|
||||
*/
|
||||
void idForce_Drag::RemovePhysics( const idPhysics *phys ) {
|
||||
if ( physics == phys ) {
|
||||
physics = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
#ifndef __FORCE_DRAG_H__
|
||||
#define __FORCE_DRAG_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Drag force
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idForce_Drag : public idForce {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idForce_Drag );
|
||||
|
||||
idForce_Drag( void );
|
||||
virtual ~idForce_Drag( void );
|
||||
// initialize the drag force
|
||||
void Init( float damping );
|
||||
// set physics object being dragged
|
||||
void SetPhysics( idPhysics *physics, int id, const idVec3 &p );
|
||||
// set position to drag towards
|
||||
void SetDragPosition( const idVec3 &pos );
|
||||
// get the position dragged towards
|
||||
const idVec3 & GetDragPosition( void ) const;
|
||||
// get the position on the dragged physics object
|
||||
const idVec3 GetDraggedPosition( void ) const;
|
||||
|
||||
public: // common force interface
|
||||
virtual void Evaluate( int time );
|
||||
virtual void RemovePhysics( const idPhysics *phys );
|
||||
|
||||
private:
|
||||
|
||||
// properties
|
||||
float damping;
|
||||
|
||||
// positioning
|
||||
idPhysics * physics; // physics object
|
||||
int id; // clip model id of physics object
|
||||
idVec3 p; // position on clip model
|
||||
idVec3 dragPosition; // drag towards this position
|
||||
};
|
||||
|
||||
#endif /* !__FORCE_DRAG_H__ */
|
||||
@@ -0,0 +1,272 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idForce, idForce_Field )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::idForce_Field
|
||||
================
|
||||
*/
|
||||
idForce_Field::idForce_Field( void ) {
|
||||
type = FORCEFIELD_UNIFORM;
|
||||
applyType = FORCEFIELD_APPLY_FORCE;
|
||||
magnitude = 0.0f;
|
||||
dir.Set( 0, 0, 1 );
|
||||
randomTorque = 0.0f;
|
||||
playerOnly = false;
|
||||
monsterOnly = false;
|
||||
clipModel = NULL;
|
||||
// RAVEN BEGIN
|
||||
// bdube: added last apply time
|
||||
lastApplyTime = -1;
|
||||
owner = NULL;
|
||||
// RAVEN END
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::~idForce_Field
|
||||
================
|
||||
*/
|
||||
idForce_Field::~idForce_Field( void ) {
|
||||
if ( this->clipModel ) {
|
||||
delete this->clipModel;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::Save
|
||||
================
|
||||
*/
|
||||
void idForce_Field::Save( idSaveGame *savefile ) const {
|
||||
savefile->WriteInt( type );
|
||||
savefile->WriteInt( applyType);
|
||||
savefile->WriteFloat( magnitude );
|
||||
savefile->WriteVec3( dir );
|
||||
savefile->WriteFloat( randomTorque );
|
||||
savefile->WriteBool( playerOnly );
|
||||
savefile->WriteBool( monsterOnly );
|
||||
savefile->WriteClipModel( clipModel );
|
||||
|
||||
savefile->WriteInt ( lastApplyTime ); // cnicholson: Added unsaved var
|
||||
// TOSAVE: idEntity* owner;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::Restore
|
||||
================
|
||||
*/
|
||||
void idForce_Field::Restore( idRestoreGame *savefile ) {
|
||||
savefile->ReadInt( (int &)type );
|
||||
savefile->ReadInt( (int &)applyType);
|
||||
savefile->ReadFloat( magnitude );
|
||||
savefile->ReadVec3( dir );
|
||||
savefile->ReadFloat( randomTorque );
|
||||
savefile->ReadBool( playerOnly );
|
||||
savefile->ReadBool( monsterOnly );
|
||||
savefile->ReadClipModel( clipModel );
|
||||
|
||||
savefile->ReadInt ( lastApplyTime ); // cnicholson: Added unrestored var
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::SetClipModel
|
||||
================
|
||||
*/
|
||||
void idForce_Field::SetClipModel( idClipModel *clipModel ) {
|
||||
if ( this->clipModel && clipModel != this->clipModel ) {
|
||||
delete this->clipModel;
|
||||
}
|
||||
this->clipModel = clipModel;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::Uniform
|
||||
================
|
||||
*/
|
||||
void idForce_Field::Uniform( const idVec3 &force ) {
|
||||
dir = force;
|
||||
magnitude = dir.Normalize();
|
||||
type = FORCEFIELD_UNIFORM;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::Explosion
|
||||
================
|
||||
*/
|
||||
void idForce_Field::Explosion( float force ) {
|
||||
magnitude = force;
|
||||
type = FORCEFIELD_EXPLOSION;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::Implosion
|
||||
================
|
||||
*/
|
||||
void idForce_Field::Implosion( float force ) {
|
||||
magnitude = force;
|
||||
type = FORCEFIELD_IMPLOSION;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::RandomTorque
|
||||
================
|
||||
*/
|
||||
void idForce_Field::RandomTorque( float force ) {
|
||||
randomTorque = force;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Field::Evaluate
|
||||
================
|
||||
*/
|
||||
void idForce_Field::Evaluate( int time ) {
|
||||
int numClipModels, i;
|
||||
idBounds bounds;
|
||||
idVec3 force, torque, angularVelocity;
|
||||
idClipModel *cm, *clipModelList[ MAX_GENTITIES ];
|
||||
|
||||
assert( clipModel );
|
||||
|
||||
bounds.FromTransformedBounds( clipModel->GetBounds(), clipModel->GetOrigin(), clipModel->GetAxis() );
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
numClipModels = gameLocal.ClipModelsTouchingBounds( owner, bounds, -1, clipModelList, MAX_GENTITIES );
|
||||
// RAVEN END
|
||||
|
||||
for ( i = 0; i < numClipModels; i++ ) {
|
||||
cm = clipModelList[ i ];
|
||||
|
||||
if ( !cm->IsTraceModel() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
idEntity *entity = cm->GetEntity();
|
||||
|
||||
if ( !entity ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
idPhysics *physics = entity->GetPhysics();
|
||||
|
||||
if ( playerOnly ) {
|
||||
// RAVEN BEGIN
|
||||
// jnewquist: Use accessor for static class type
|
||||
if ( !physics->IsType( idPhysics_Player::GetClassType() ) ) {
|
||||
// RAVEN END
|
||||
continue;
|
||||
}
|
||||
} else if ( monsterOnly ) {
|
||||
// RAVEN BEGIN
|
||||
// jnewquist: Use accessor for static class type
|
||||
if ( !physics->IsType( idPhysics_Monster::GetClassType() ) ) {
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// nrausch: It was undesireable to have gibs and discarded weapons bouncing on jump pads
|
||||
if ( gameLocal.isMultiplayer ) {
|
||||
if ( entity->IsType( idItem::GetClassType() ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( entity->IsType( rvClientPhysics::GetClassType() ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( entity->IsType( idPlayer::GetClassType() ) ) {
|
||||
if ( ((idPlayer*)entity)->health <= 0 ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ddynerman: multiple clip worlds
|
||||
if ( !gameLocal.ContentsModel( owner, cm->GetOrigin(), cm, cm->GetAxis(), -1,
|
||||
clipModel->GetCollisionModel(), clipModel->GetOrigin(), clipModel->GetAxis() ) ) {
|
||||
// RAVEN END
|
||||
continue;
|
||||
}
|
||||
|
||||
switch( type ) {
|
||||
case FORCEFIELD_UNIFORM: {
|
||||
force = dir;
|
||||
break;
|
||||
}
|
||||
case FORCEFIELD_EXPLOSION: {
|
||||
force = cm->GetOrigin() - clipModel->GetOrigin();
|
||||
force.Normalize();
|
||||
break;
|
||||
}
|
||||
case FORCEFIELD_IMPLOSION: {
|
||||
force = clipModel->GetOrigin() - cm->GetOrigin();
|
||||
force.Normalize();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
gameLocal.Error( "idForce_Field: invalid type" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( randomTorque != 0.0f ) {
|
||||
torque[0] = gameLocal.random.CRandomFloat();
|
||||
torque[1] = gameLocal.random.CRandomFloat();
|
||||
torque[2] = gameLocal.random.CRandomFloat();
|
||||
if ( torque.Normalize() == 0.0f ) {
|
||||
torque[2] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
switch( applyType ) {
|
||||
case FORCEFIELD_APPLY_FORCE: {
|
||||
if ( randomTorque != 0.0f ) {
|
||||
entity->AddForce( gameLocal.world, cm->GetId(), cm->GetOrigin() + torque.Cross( dir ) * randomTorque, dir * magnitude );
|
||||
}
|
||||
else {
|
||||
entity->AddForce( gameLocal.world, cm->GetId(), cm->GetOrigin(), force * magnitude );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FORCEFIELD_APPLY_VELOCITY: {
|
||||
physics->SetLinearVelocity( force * magnitude, cm->GetId() );
|
||||
if ( randomTorque != 0.0f ) {
|
||||
angularVelocity = physics->GetAngularVelocity( cm->GetId() );
|
||||
physics->SetAngularVelocity( 0.5f * (angularVelocity + torque * randomTorque), cm->GetId() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FORCEFIELD_APPLY_IMPULSE: {
|
||||
if ( randomTorque != 0.0f ) {
|
||||
entity->ApplyImpulse( gameLocal.world, cm->GetId(), cm->GetOrigin() + torque.Cross( dir ) * randomTorque, dir * magnitude );
|
||||
}
|
||||
else {
|
||||
entity->ApplyImpulse( gameLocal.world, cm->GetId(), cm->GetOrigin(), force * magnitude );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
gameLocal.Error( "idForce_Field: invalid apply type" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: added last apply time
|
||||
lastApplyTime = time;
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
#ifndef __FORCE_FIELD_H__
|
||||
#define __FORCE_FIELD_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Force field
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
enum forceFieldType {
|
||||
FORCEFIELD_UNIFORM,
|
||||
FORCEFIELD_EXPLOSION,
|
||||
FORCEFIELD_IMPLOSION
|
||||
};
|
||||
|
||||
enum forceFieldApplyType {
|
||||
FORCEFIELD_APPLY_FORCE,
|
||||
FORCEFIELD_APPLY_VELOCITY,
|
||||
FORCEFIELD_APPLY_IMPULSE
|
||||
};
|
||||
|
||||
class idForce_Field : public idForce {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idForce_Field );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
idForce_Field( void );
|
||||
virtual ~idForce_Field( void );
|
||||
// uniform constant force
|
||||
void Uniform( const idVec3 &force );
|
||||
// explosion from clip model origin
|
||||
void Explosion( float force );
|
||||
// implosion towards clip model origin
|
||||
void Implosion( float force );
|
||||
// add random torque
|
||||
void RandomTorque( float force );
|
||||
// should the force field apply a force, velocity or impulse
|
||||
void SetApplyType( const forceFieldApplyType type ) { applyType = type; }
|
||||
// make the force field only push players
|
||||
void SetPlayerOnly( bool set ) { playerOnly = set; }
|
||||
// make the force field only push monsters
|
||||
void SetMonsterOnly( bool set ) { monsterOnly = set; }
|
||||
// clip model describing the extents of the force field
|
||||
void SetClipModel( idClipModel *clipModel );
|
||||
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: owner information
|
||||
void SetOwner( idEntity* ent );
|
||||
// bdube: added last apply time
|
||||
int GetLastApplyTime( void ) const;
|
||||
// RAVEN END
|
||||
|
||||
public: // common force interface
|
||||
virtual void Evaluate( int time );
|
||||
|
||||
private:
|
||||
// force properties
|
||||
forceFieldType type;
|
||||
forceFieldApplyType applyType;
|
||||
float magnitude;
|
||||
idVec3 dir;
|
||||
float randomTorque;
|
||||
bool playerOnly;
|
||||
bool monsterOnly;
|
||||
idClipModel * clipModel;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: added last apply time
|
||||
int lastApplyTime;
|
||||
idEntity* owner;
|
||||
// RAVEN END
|
||||
};
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: added last apply time
|
||||
ID_INLINE int idForce_Field::GetLastApplyTime ( void ) const {
|
||||
return lastApplyTime;
|
||||
}
|
||||
|
||||
// ddynerman: owner information
|
||||
ID_INLINE void idForce_Field::SetOwner( idEntity* ent ) {
|
||||
owner = ent;
|
||||
}
|
||||
// RAVEN END
|
||||
|
||||
#endif /* !__FORCE_FIELD_H__ */
|
||||
@@ -0,0 +1,163 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idForce, idForce_Spring )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Spring::idForce_Spring
|
||||
================
|
||||
*/
|
||||
idForce_Spring::idForce_Spring( void ) {
|
||||
Kstretch = 100.0f;
|
||||
Kcompress = 100.0f;
|
||||
damping = 0.0f;
|
||||
restLength = 0.0f;
|
||||
physics1 = NULL;
|
||||
id1 = 0;
|
||||
p1 = vec3_zero;
|
||||
physics2 = NULL;
|
||||
id2 = 0;
|
||||
p2 = vec3_zero;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Spring::~idForce_Spring
|
||||
================
|
||||
*/
|
||||
idForce_Spring::~idForce_Spring( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Spring::InitSpring
|
||||
================
|
||||
*/
|
||||
void idForce_Spring::InitSpring( float Kstretch, float Kcompress, float damping, float restLength ) {
|
||||
this->Kstretch = Kstretch;
|
||||
this->Kcompress = Kcompress;
|
||||
this->damping = damping;
|
||||
this->restLength = restLength;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Spring::SetPosition
|
||||
================
|
||||
*/
|
||||
void idForce_Spring::SetPosition( idPhysics *physics1, int id1, const idVec3 &p1, idPhysics *physics2, int id2, const idVec3 &p2 ) {
|
||||
this->physics1 = physics1;
|
||||
this->id1 = id1;
|
||||
this->p1 = p1;
|
||||
this->physics2 = physics2;
|
||||
this->id2 = id2;
|
||||
this->p2 = p2;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Spring::Evaluate
|
||||
================
|
||||
*/
|
||||
void idForce_Spring::Evaluate( int time ) {
|
||||
float length;
|
||||
idMat3 axis;
|
||||
idVec3 pos1, pos2, velocity1, velocity2, force, dampingForce;
|
||||
impactInfo_t info;
|
||||
|
||||
pos1 = p1;
|
||||
pos2 = p2;
|
||||
velocity1 = velocity2 = vec3_origin;
|
||||
|
||||
if ( physics1 ) {
|
||||
axis = physics1->GetAxis( id1 );
|
||||
pos1 = physics1->GetOrigin( id1 );
|
||||
pos1 += p1 * axis;
|
||||
if ( damping > 0.0f ) {
|
||||
physics1->GetImpactInfo( id1, pos1, &info );
|
||||
velocity1 = info.velocity;
|
||||
}
|
||||
}
|
||||
|
||||
if ( physics2 ) {
|
||||
axis = physics2->GetAxis( id2 );
|
||||
pos2 = physics2->GetOrigin( id2 );
|
||||
pos2 += p2 * axis;
|
||||
if ( damping > 0.0f ) {
|
||||
physics2->GetImpactInfo( id2, pos2, &info );
|
||||
velocity2 = info.velocity;
|
||||
}
|
||||
}
|
||||
|
||||
force = pos2 - pos1;
|
||||
dampingForce = ( damping * ( ((velocity2 - velocity1) * force) / (force * force) ) ) * force;
|
||||
length = force.Normalize();
|
||||
|
||||
// if the spring is stretched
|
||||
if ( length > restLength ) {
|
||||
if ( Kstretch > 0.0f ) {
|
||||
force = ( Square( length - restLength ) * Kstretch ) * force - dampingForce;
|
||||
if ( physics1 ) {
|
||||
physics1->AddForce( id1, pos1, force );
|
||||
}
|
||||
if ( physics2 ) {
|
||||
physics2->AddForce( id2, pos2, -force );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( Kcompress > 0.0f ) {
|
||||
force = ( Square( length - restLength ) * Kcompress ) * force - dampingForce;
|
||||
if ( physics1 ) {
|
||||
physics1->AddForce( id1, pos1, -force );
|
||||
}
|
||||
if ( physics2 ) {
|
||||
physics2->AddForce( id2, pos2, force );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Spring::RemovePhysics
|
||||
================
|
||||
*/
|
||||
void idForce_Spring::RemovePhysics( const idPhysics *phys ) {
|
||||
if ( physics1 == phys ) {
|
||||
physics1 = NULL;
|
||||
}
|
||||
if ( physics2 == phys ) {
|
||||
physics2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Spring::Save
|
||||
================
|
||||
*/
|
||||
void idForce_Spring::Save( idSaveGame *savefile ) const {
|
||||
savefile->WriteFloat ( Kstretch );
|
||||
savefile->WriteFloat ( Kcompress );
|
||||
savefile->WriteFloat ( damping );
|
||||
savefile->WriteFloat ( restLength );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idForce_Spring::Restore
|
||||
================
|
||||
*/
|
||||
void idForce_Spring::Restore( idRestoreGame *savefile ) {
|
||||
savefile->ReadFloat ( Kstretch );
|
||||
savefile->ReadFloat ( Kcompress );
|
||||
savefile->ReadFloat ( damping );
|
||||
savefile->ReadFloat ( restLength );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
#ifndef __FORCE_SPRING_H__
|
||||
#define __FORCE_SPRING_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Spring force
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idForce_Spring : public idForce {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idForce_Spring );
|
||||
|
||||
idForce_Spring( void );
|
||||
virtual ~idForce_Spring( void );
|
||||
// initialize the spring
|
||||
void InitSpring( float Kstretch, float Kcompress, float damping, float restLength );
|
||||
// set the entities and positions on these entities the spring is attached to
|
||||
void SetPosition( idPhysics *physics1, int id1, const idVec3 &p1,
|
||||
idPhysics *physics2, int id2, const idVec3 &p2 );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
public: // common force interface
|
||||
virtual void Evaluate( int time );
|
||||
virtual void RemovePhysics( const idPhysics *phys );
|
||||
|
||||
private:
|
||||
|
||||
// spring properties
|
||||
float Kstretch;
|
||||
float Kcompress;
|
||||
float damping;
|
||||
float restLength;
|
||||
|
||||
// positioning
|
||||
idPhysics * physics1; // first physics object
|
||||
int id1; // clip model id of first physics object
|
||||
idVec3 p1; // position on clip model
|
||||
idPhysics * physics2; // second physics object
|
||||
int id2; // clip model id of second physics object
|
||||
idVec3 p2; // position on clip model
|
||||
|
||||
};
|
||||
|
||||
#endif /* !__FORCE_SPRING_H__ */
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
ABSTRACT_DECLARATION( idClass, idPhysics )
|
||||
END_CLASS
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics::~idPhysics
|
||||
================
|
||||
*/
|
||||
idPhysics::~idPhysics( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics::Save
|
||||
================
|
||||
*/
|
||||
void idPhysics::Save( idSaveGame *savefile ) const {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics::Restore
|
||||
================
|
||||
*/
|
||||
void idPhysics::Restore( idRestoreGame *savefile ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics::SetClipBox
|
||||
================
|
||||
*/
|
||||
void idPhysics::SetClipBox( const idBounds &bounds, float density ) {
|
||||
SetClipModel( new idClipModel( idTraceModel( bounds ) ), density );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics::SnapTimeToPhysicsFrame
|
||||
================
|
||||
*/
|
||||
int idPhysics::SnapTimeToPhysicsFrame( int t ) {
|
||||
int s;
|
||||
// RAVEN BEGIN
|
||||
// bdube: use GetMSec access rather than USERCMD_TIME
|
||||
s = t + gameLocal.GetMSec() - 1;
|
||||
return ( s - s % gameLocal.GetMSec() );
|
||||
// RAVEN END
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
|
||||
#ifndef __PHYSICS_H__
|
||||
#define __PHYSICS_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Physics abstract class
|
||||
|
||||
A physics object is a tool to manipulate the position and orientation of
|
||||
an entity. The physics object is a container for idClipModels used for
|
||||
collision detection. The physics deals with moving these collision models
|
||||
through the world according to the laws of physics or other rules.
|
||||
|
||||
The mass of a clip model is the volume of the clip model times the density.
|
||||
An arbitrary mass can however be set for specific clip models or the
|
||||
whole physics object. The contents of a clip model is a set of bit flags
|
||||
that define the contents. The clip mask defines the contents a clip model
|
||||
collides with.
|
||||
|
||||
The linear velocity of a physics object is a vector that defines the
|
||||
translation of the center of mass in units per second. The angular velocity
|
||||
of a physics object is a vector that passes through the center of mass. The
|
||||
direction of this vector defines the axis of rotation and the magnitude
|
||||
defines the rate of rotation about the axis in radians per second.
|
||||
The gravity is the change in velocity per second due to gravitational force.
|
||||
|
||||
Entities update their visual position and orientation from the physics
|
||||
using GetOrigin() and GetAxis(). Direct origin and axis changes of
|
||||
entities should go through the physics. In other words the physics origin
|
||||
and axis are updated first and the entity updates it's visual position
|
||||
from the physics.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#define CONTACT_EPSILON 0.25f // maximum contact seperation distance
|
||||
|
||||
class idEntity;
|
||||
|
||||
typedef struct impactInfo_s {
|
||||
float invMass; // inverse mass
|
||||
idMat3 invInertiaTensor; // inverse inertia tensor
|
||||
idVec3 position; // impact position relative to center of mass
|
||||
idVec3 velocity; // velocity at the impact position
|
||||
} impactInfo_t;
|
||||
|
||||
|
||||
class idPhysics : public idClass {
|
||||
|
||||
public:
|
||||
ABSTRACT_PROTOTYPE( idPhysics );
|
||||
|
||||
virtual ~idPhysics( void );
|
||||
static int SnapTimeToPhysicsFrame( int t );
|
||||
|
||||
// Must not be virtual
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
public: // common physics interface
|
||||
// set pointer to entity using physics
|
||||
virtual void SetSelf( idEntity *e ) = 0;
|
||||
// clip models
|
||||
virtual void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true ) = 0;
|
||||
virtual void SetClipBox( const idBounds &bounds, float density );
|
||||
virtual idClipModel * GetClipModel( int id = 0 ) const = 0;
|
||||
virtual int GetNumClipModels( void ) const = 0;
|
||||
// get/set the mass of a specific clip model or the whole physics object
|
||||
virtual void SetMass( float mass, int id = -1 ) = 0;
|
||||
virtual float GetMass( int id = -1 ) const = 0;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: added center mass
|
||||
// get the center of mass origin
|
||||
virtual idVec3 GetCenterMass ( int id = -1 ) const = 0;
|
||||
// RAVEN END
|
||||
|
||||
// get/set the contents of a specific clip model or the whole physics object
|
||||
virtual void SetContents( int contents, int id = -1 ) = 0;
|
||||
virtual int GetContents( int id = -1 ) const = 0;
|
||||
// get/set the contents a specific clip model or the whole physics object collides with
|
||||
virtual void SetClipMask( int mask, int id = -1 ) = 0;
|
||||
virtual int GetClipMask( int id = -1 ) const = 0;
|
||||
// get the bounds of a specific clip model or the whole physics object
|
||||
virtual const idBounds & GetBounds( int id = -1 ) const = 0;
|
||||
virtual const idBounds & GetAbsBounds( int id = -1 ) const = 0;
|
||||
// evaluate the physics with the given time step, returns true if the object moved
|
||||
virtual bool Evaluate( int timeStepMSec, int endTimeMSec ) = 0;
|
||||
// update the time without moving
|
||||
virtual void UpdateTime( int endTimeMSec ) = 0;
|
||||
// get the last physics update time
|
||||
virtual int GetTime( void ) const = 0;
|
||||
// collision interaction between different physics objects
|
||||
virtual void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const = 0;
|
||||
virtual void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) = 0;
|
||||
virtual void AddForce( const int id, const idVec3 &point, const idVec3 &force ) = 0;
|
||||
virtual void Activate( void ) = 0;
|
||||
virtual void PutToRest( void ) = 0;
|
||||
virtual bool IsAtRest( void ) const = 0;
|
||||
virtual int GetRestStartTime( void ) const = 0;
|
||||
virtual bool IsPushable( void ) const = 0;
|
||||
// RAVEN BEGIN
|
||||
// bdube: water interraction
|
||||
virtual bool IsInWater ( void ) const = 0;
|
||||
// RAVEN END
|
||||
// save and restore the physics state
|
||||
virtual void SaveState( void ) = 0;
|
||||
virtual void RestoreState( void ) = 0;
|
||||
// set the position and orientation in master space or world space if no master set
|
||||
virtual void SetOrigin( const idVec3 &newOrigin, int id = -1 ) = 0;
|
||||
virtual void SetAxis( const idMat3 &newAxis, int id = -1 ) = 0;
|
||||
// translate or rotate the physics object in world space
|
||||
virtual void Translate( const idVec3 &translation, int id = -1 ) = 0;
|
||||
virtual void Rotate( const idRotation &rotation, int id = -1 ) = 0;
|
||||
// get the position and orientation in world space
|
||||
virtual const idVec3 & GetOrigin( int id = 0 ) const = 0;
|
||||
virtual const idMat3 & GetAxis( int id = 0 ) const = 0;
|
||||
// set linear and angular velocity
|
||||
virtual void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 ) = 0;
|
||||
virtual void SetAngularVelocity( const idVec3 &newAngularVelocity, int id = 0 ) = 0;
|
||||
// get linear and angular velocity
|
||||
virtual const idVec3 & GetLinearVelocity( int id = 0 ) const = 0;
|
||||
virtual const idVec3 & GetAngularVelocity( int id = 0 ) const = 0;
|
||||
// gravity
|
||||
virtual void SetGravity( const idVec3 &newGravity ) = 0;
|
||||
virtual const idVec3 & GetGravity( void ) const = 0;
|
||||
virtual const idVec3 & GetGravityNormal( void ) const = 0;
|
||||
// get first collision when translating or rotating this physics object
|
||||
virtual void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const = 0;
|
||||
virtual void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const = 0;
|
||||
virtual int ClipContents( const idClipModel *model ) const = 0;
|
||||
// disable/enable the clip models contained by this physics object
|
||||
virtual void DisableClip( void ) = 0;
|
||||
virtual void EnableClip( void ) = 0;
|
||||
// link/unlink the clip models contained by this physics object
|
||||
virtual void UnlinkClip( void ) = 0;
|
||||
virtual void LinkClip( void ) = 0;
|
||||
// contacts
|
||||
virtual bool EvaluateContacts( void ) = 0;
|
||||
virtual int GetNumContacts( void ) const = 0;
|
||||
virtual const contactInfo_t &GetContact( int num ) const = 0;
|
||||
virtual void ClearContacts( void ) = 0;
|
||||
virtual void AddContactEntity( idEntity *e ) = 0;
|
||||
virtual void RemoveContactEntity( idEntity *e ) = 0;
|
||||
// ground contacts
|
||||
virtual bool HasGroundContacts( void ) const = 0;
|
||||
virtual bool IsGroundEntity( int entityNum ) const = 0;
|
||||
virtual bool IsGroundClipModel( int entityNum, int id ) const = 0;
|
||||
// RAVEN BEGIN
|
||||
// abahr
|
||||
virtual const idVec3 GetContactNormal() const { return vec3_zero; }
|
||||
virtual const idVec3 GetGroundContactNormal() const { return vec3_zero; }
|
||||
virtual idEntity* GetSelf() const = 0;
|
||||
// RAVEN END
|
||||
// set the master entity for objects bound to a master
|
||||
virtual void SetMaster( idEntity *master, const bool orientated = true ) = 0;
|
||||
// set pushed state
|
||||
virtual void SetPushed( int deltaTime ) = 0;
|
||||
virtual const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const = 0;
|
||||
virtual const idVec3 & GetPushedAngularVelocity( const int id = 0 ) const = 0;
|
||||
// get blocking info, returns NULL if the object is not blocked
|
||||
virtual const trace_t * GetBlockingInfo( void ) const = 0;
|
||||
virtual idEntity * GetBlockingEntity( void ) const = 0;
|
||||
// movement end times in msec for reached events at the end of predefined motion
|
||||
virtual int GetLinearEndTime( void ) const = 0;
|
||||
virtual int GetAngularEndTime( void ) const = 0;
|
||||
// networking
|
||||
virtual void WriteToSnapshot( idBitMsgDelta &msg ) const = 0;
|
||||
virtual void ReadFromSnapshot( const idBitMsgDelta &msg ) = 0;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// kfuller: we want to debug draw the bbox
|
||||
virtual void DebugDraw() {}
|
||||
// RAVEN END
|
||||
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,988 @@
|
||||
|
||||
#ifndef __PHYSICS_AF_H__
|
||||
#define __PHYSICS_AF_H__
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
Articulated Figure physics
|
||||
|
||||
Employs a constraint force based dynamic simulation using a lagrangian
|
||||
multiplier method to solve for the constraint forces.
|
||||
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
class idAFConstraint;
|
||||
class idAFConstraint_Fixed;
|
||||
class idAFConstraint_BallAndSocketJoint;
|
||||
class idAFConstraint_BallAndSocketJointFriction;
|
||||
class idAFConstraint_UniversalJoint;
|
||||
class idAFConstraint_UniversalJointFriction;
|
||||
class idAFConstraint_CylindricalJoint;
|
||||
class idAFConstraint_Hinge;
|
||||
class idAFConstraint_HingeFriction;
|
||||
class idAFConstraint_HingeSteering;
|
||||
class idAFConstraint_Slider;
|
||||
class idAFConstraint_Line;
|
||||
class idAFConstraint_Plane;
|
||||
class idAFConstraint_Spring;
|
||||
class idAFConstraint_Contact;
|
||||
class idAFConstraint_ContactFriction;
|
||||
class idAFConstraint_ConeLimit;
|
||||
class idAFConstraint_PyramidLimit;
|
||||
class idAFBody;
|
||||
class idAFTree;
|
||||
class idPhysics_AF;
|
||||
|
||||
typedef enum {
|
||||
CONSTRAINT_INVALID,
|
||||
CONSTRAINT_FIXED,
|
||||
CONSTRAINT_BALLANDSOCKETJOINT,
|
||||
CONSTRAINT_UNIVERSALJOINT,
|
||||
CONSTRAINT_HINGE,
|
||||
CONSTRAINT_HINGESTEERING,
|
||||
CONSTRAINT_SLIDER,
|
||||
CONSTRAINT_CYLINDRICALJOINT,
|
||||
CONSTRAINT_LINE,
|
||||
CONSTRAINT_PLANE,
|
||||
CONSTRAINT_SPRING,
|
||||
CONSTRAINT_CONTACT,
|
||||
CONSTRAINT_FRICTION,
|
||||
CONSTRAINT_CONELIMIT,
|
||||
CONSTRAINT_PYRAMIDLIMIT
|
||||
} constraintType_t;
|
||||
|
||||
|
||||
//===============================================================
|
||||
//
|
||||
// idAFConstraint
|
||||
//
|
||||
//===============================================================
|
||||
|
||||
// base class for all constraints
|
||||
class idAFConstraint {
|
||||
|
||||
friend class idPhysics_AF;
|
||||
friend class idAFTree;
|
||||
|
||||
public:
|
||||
idAFConstraint( void );
|
||||
virtual ~idAFConstraint( void );
|
||||
constraintType_t GetType( void ) const { return type; }
|
||||
const idStr & GetName( void ) const { return name; }
|
||||
idAFBody * GetBody1( void ) const { return body1; }
|
||||
idAFBody * GetBody2( void ) const { return body2; }
|
||||
void SetPhysics( idPhysics_AF *p ) { physics = p; }
|
||||
const idVecX & GetMultiplier( void );
|
||||
virtual void SetBody1( idAFBody *body );
|
||||
virtual void SetBody2( idAFBody *body );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void GetForce( idAFBody *body, idVec6 &force );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void GetCenter( idVec3 ¢er );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
constraintType_t type; // constraint type
|
||||
idStr name; // name of constraint
|
||||
idAFBody * body1; // first constrained body
|
||||
idAFBody * body2; // second constrained body, NULL for world
|
||||
idPhysics_AF * physics; // for adding additional constraints like limits
|
||||
|
||||
// simulation variables set by Evaluate
|
||||
idMatX J1, J2; // matrix with left hand side of constraint equations
|
||||
idVecX c1, c2; // right hand side of constraint equations
|
||||
idVecX lo, hi, e; // low and high bounds and lcp epsilon
|
||||
idAFConstraint * boxConstraint; // constraint the boxIndex refers to
|
||||
int boxIndex[6]; // indexes for special box constrained variables
|
||||
|
||||
// simulation variables used during calculations
|
||||
idMatX invI; // transformed inertia
|
||||
idMatX J; // transformed constraint matrix
|
||||
idVecX s; // temp solution
|
||||
idVecX lm; // lagrange multipliers
|
||||
int firstIndex; // index of the first constraint row in the lcp matrix
|
||||
|
||||
struct constraintFlags_s {
|
||||
bool allowPrimary : 1; // true if the constraint can be used as a primary constraint
|
||||
bool frameConstraint : 1; // true if this constraint is added to the frame constraints
|
||||
bool noCollision : 1; // true if body1 and body2 never collide with each other
|
||||
bool isPrimary : 1; // true if this is a primary constraint
|
||||
bool isZero : 1; // true if 's' is zero during calculations
|
||||
} fl;
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
void InitSize( int size );
|
||||
};
|
||||
|
||||
// fixed or rigid joint which allows zero degrees of freedom
|
||||
// constrains body1 to have a fixed position and orientation relative to body2
|
||||
class idAFConstraint_Fixed : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_Fixed( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
void SetRelativeOrigin( const idVec3 &origin ) { this->offset = origin; }
|
||||
void SetRelativeAxis( const idMat3 &axis ) { this->relAxis = axis; }
|
||||
virtual void SetBody1( idAFBody *body );
|
||||
virtual void SetBody2( idAFBody *body );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void GetCenter( idVec3 ¢er );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 offset; // offset of body1 relative to body2 in body2 space
|
||||
idMat3 relAxis; // rotation of body1 relative to body2
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
void InitOffset( void );
|
||||
};
|
||||
|
||||
// ball and socket or spherical joint which allows 3 degrees of freedom
|
||||
// constrains body1 relative to body2 with a ball and socket joint
|
||||
class idAFConstraint_BallAndSocketJoint : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_BallAndSocketJoint( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
~idAFConstraint_BallAndSocketJoint( void );
|
||||
void SetAnchor( const idVec3 &worldPosition );
|
||||
idVec3 GetAnchor( void ) const;
|
||||
void SetNoLimit( void );
|
||||
void SetConeLimit( const idVec3 &coneAxis, const float coneAngle, const idVec3 &body1Axis );
|
||||
void SetPyramidLimit( const idVec3 &pyramidAxis, const idVec3 &baseAxis,
|
||||
const float angle1, const float angle2, const idVec3 &body1Axis );
|
||||
void SetLimitEpsilon( const float e );
|
||||
void SetFriction( const float f ) { friction = f; }
|
||||
float GetFriction( void ) const;
|
||||
virtual void DebugDraw( void );
|
||||
virtual void GetForce( idAFBody *body, idVec6 &force );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void GetCenter( idVec3 ¢er );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 anchor1; // anchor in body1 space
|
||||
idVec3 anchor2; // anchor in body2 space
|
||||
float friction; // joint friction
|
||||
idAFConstraint_ConeLimit *coneLimit; // cone shaped limit
|
||||
idAFConstraint_PyramidLimit *pyramidLimit; // pyramid shaped limit
|
||||
idAFConstraint_BallAndSocketJointFriction *fc; // friction constraint
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// ball and socket joint friction
|
||||
class idAFConstraint_BallAndSocketJointFriction : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_BallAndSocketJointFriction( void );
|
||||
void Setup( idAFConstraint_BallAndSocketJoint *cc );
|
||||
bool Add( idPhysics_AF *phys, float invTimeStep );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
|
||||
protected:
|
||||
idAFConstraint_BallAndSocketJoint *joint;
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// universal, Cardan or Hooke joint which allows 2 degrees of freedom
|
||||
// like a ball and socket joint but also constrains the rotation about the cardan shafts
|
||||
class idAFConstraint_UniversalJoint : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_UniversalJoint( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
~idAFConstraint_UniversalJoint( void );
|
||||
void SetAnchor( const idVec3 &worldPosition );
|
||||
idVec3 GetAnchor( void ) const;
|
||||
void SetShafts( const idVec3 &cardanShaft1, const idVec3 &cardanShaft2 );
|
||||
void GetShafts( idVec3 &cardanShaft1, idVec3 &cardanShaft2 ) { cardanShaft1 = shaft1; cardanShaft2 = shaft2; }
|
||||
void SetNoLimit( void );
|
||||
void SetConeLimit( const idVec3 &coneAxis, const float coneAngle );
|
||||
void SetPyramidLimit( const idVec3 &pyramidAxis, const idVec3 &baseAxis,
|
||||
const float angle1, const float angle2 );
|
||||
void SetLimitEpsilon( const float e );
|
||||
void SetFriction( const float f ) { friction = f; }
|
||||
float GetFriction( void ) const;
|
||||
virtual void DebugDraw( void );
|
||||
virtual void GetForce( idAFBody *body, idVec6 &force );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void GetCenter( idVec3 ¢er );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 anchor1; // anchor in body1 space
|
||||
idVec3 anchor2; // anchor in body2 space
|
||||
idVec3 shaft1; // body1 cardan shaft in body1 space
|
||||
idVec3 shaft2; // body2 cardan shaft in body2 space
|
||||
idVec3 axis1; // cardan axis in body1 space
|
||||
idVec3 axis2; // cardan axis in body2 space
|
||||
float friction; // joint friction
|
||||
idAFConstraint_ConeLimit *coneLimit; // cone shaped limit
|
||||
idAFConstraint_PyramidLimit *pyramidLimit; // pyramid shaped limit
|
||||
idAFConstraint_UniversalJointFriction *fc; // friction constraint
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// universal joint friction
|
||||
class idAFConstraint_UniversalJointFriction : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_UniversalJointFriction( void );
|
||||
void Setup( idAFConstraint_UniversalJoint *cc );
|
||||
bool Add( idPhysics_AF *phys, float invTimeStep );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
|
||||
protected:
|
||||
idAFConstraint_UniversalJoint *joint; // universal joint
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// cylindrical joint which allows 2 degrees of freedom
|
||||
// constrains body1 to lie on a line relative to body2 and allows only translation along and rotation about the line
|
||||
class idAFConstraint_CylindricalJoint : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_CylindricalJoint( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
|
||||
protected:
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// hinge, revolute or pin joint which allows 1 degree of freedom
|
||||
// constrains all motion of body1 relative to body2 except the rotation about the hinge axis
|
||||
class idAFConstraint_Hinge : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_Hinge( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
~idAFConstraint_Hinge( void );
|
||||
void SetAnchor( const idVec3 &worldPosition );
|
||||
idVec3 GetAnchor( void ) const;
|
||||
void SetAxis( const idVec3 &axis );
|
||||
void GetAxis( idVec3 &a1, idVec3 &a2 ) const { a1 = axis1; a2 = axis2; }
|
||||
idVec3 GetAxis( void ) const;
|
||||
void SetNoLimit( void );
|
||||
void SetLimit( const idVec3 &axis, const float angle, const idVec3 &body1Axis );
|
||||
void SetLimitEpsilon( const float e );
|
||||
float GetAngle( void ) const;
|
||||
void SetSteerAngle( const float degrees );
|
||||
void SetSteerSpeed( const float speed );
|
||||
void SetFriction( const float f ) { friction = f; }
|
||||
float GetFriction( void ) const;
|
||||
virtual void DebugDraw( void );
|
||||
virtual void GetForce( idAFBody *body, idVec6 &force );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void GetCenter( idVec3 ¢er );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 anchor1; // anchor in body1 space
|
||||
idVec3 anchor2; // anchor in body2 space
|
||||
idVec3 axis1; // axis in body1 space
|
||||
idVec3 axis2; // axis in body2 space
|
||||
idMat3 initialAxis; // initial axis of body1 relative to body2
|
||||
float friction; // hinge friction
|
||||
idAFConstraint_ConeLimit *coneLimit; // cone limit
|
||||
idAFConstraint_HingeSteering *steering; // steering
|
||||
idAFConstraint_HingeFriction *fc; // friction constraint
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// hinge joint friction
|
||||
class idAFConstraint_HingeFriction : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_HingeFriction( void );
|
||||
void Setup( idAFConstraint_Hinge *cc );
|
||||
bool Add( idPhysics_AF *phys, float invTimeStep );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
|
||||
protected:
|
||||
idAFConstraint_Hinge * hinge; // hinge
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// constrains two bodies attached to each other with a hinge to get a specified relative orientation
|
||||
class idAFConstraint_HingeSteering : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_HingeSteering( void );
|
||||
void Setup( idAFConstraint_Hinge *cc );
|
||||
void SetSteerAngle( const float degrees ) { steerAngle = degrees; }
|
||||
void SetSteerSpeed( const float speed ) { steerSpeed = speed; }
|
||||
void SetEpsilon( const float e ) { epsilon = e; }
|
||||
bool Add( idPhysics_AF *phys, float invTimeStep );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idAFConstraint_Hinge * hinge; // hinge
|
||||
float steerAngle; // desired steer angle in degrees
|
||||
float steerSpeed; // steer speed
|
||||
float epsilon; // lcp epsilon
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// slider, prismatic or translational constraint which allows 1 degree of freedom
|
||||
// constrains body1 to lie on a line relative to body2, the orientation is also fixed relative to body2
|
||||
class idAFConstraint_Slider : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_Slider( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
void SetAxis( const idVec3 &ax );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void GetCenter( idVec3 ¢er );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 axis; // axis along which body1 slides in body2 space
|
||||
idVec3 offset; // offset of body1 relative to body2
|
||||
idMat3 relAxis; // rotation of body1 relative to body2
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// line constraint which allows 4 degrees of freedom
|
||||
// constrains body1 to lie on a line relative to body2, does not constrain the orientation.
|
||||
class idAFConstraint_Line : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_Line( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
|
||||
protected:
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// plane constraint which allows 5 degrees of freedom
|
||||
// constrains body1 to lie in a plane relative to body2, does not constrain the orientation.
|
||||
class idAFConstraint_Plane : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_Plane( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
void SetPlane( const idVec3 &normal, const idVec3 &anchor );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 anchor1; // anchor in body1 space
|
||||
idVec3 anchor2; // anchor in body2 space
|
||||
idVec3 planeNormal; // plane normal in body2 space
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// spring constraint which allows 6 or 5 degrees of freedom based on the spring limits
|
||||
// constrains body1 relative to body2 with a spring
|
||||
class idAFConstraint_Spring : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_Spring( const idStr &name, idAFBody *body1, idAFBody *body2 );
|
||||
void SetAnchor( const idVec3 &worldAnchor1, const idVec3 &worldAnchor2 );
|
||||
void SetSpring( const float stretch, const float compress, const float damping, const float restLength );
|
||||
void SetLimit( const float minLength, const float maxLength );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void GetCenter( idVec3 ¢er );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 anchor1; // anchor in body1 space
|
||||
idVec3 anchor2; // anchor in body2 space
|
||||
float kstretch; // spring constant when stretched
|
||||
float kcompress; // spring constant when compressed
|
||||
float damping; // spring damping
|
||||
float restLength; // rest length of spring
|
||||
float minLength; // minimum spring length
|
||||
float maxLength; // maximum spring length
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// constrains body1 to either be in contact with or move away from body2
|
||||
class idAFConstraint_Contact : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_Contact( void );
|
||||
~idAFConstraint_Contact( void );
|
||||
void Setup( idAFBody *b1, idAFBody *b2, contactInfo_t &c );
|
||||
const contactInfo_t & GetContact( void ) const { return contact; }
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void GetCenter( idVec3 ¢er );
|
||||
|
||||
protected:
|
||||
contactInfo_t contact; // contact information
|
||||
idAFConstraint_ContactFriction *fc; // contact friction
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// contact friction
|
||||
class idAFConstraint_ContactFriction : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_ContactFriction( void );
|
||||
void Setup( idAFConstraint_Contact *cc );
|
||||
bool Add( idPhysics_AF *phys, float invTimeStep );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
|
||||
protected:
|
||||
idAFConstraint_Contact *cc; // contact constraint
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// constrains an axis attached to body1 to be inside a cone relative to body2
|
||||
class idAFConstraint_ConeLimit : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_ConeLimit( void );
|
||||
void Setup( idAFBody *b1, idAFBody *b2, const idVec3 &coneAnchor, const idVec3 &coneAxis,
|
||||
const float coneAngle, const idVec3 &body1Axis );
|
||||
void SetAnchor( const idVec3 &coneAnchor );
|
||||
void SetBody1Axis( const idVec3 &body1Axis );
|
||||
void SetEpsilon( const float e ) { epsilon = e; }
|
||||
bool Add( idPhysics_AF *phys, float invTimeStep );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 coneAnchor; // top of the cone in body2 space
|
||||
idVec3 coneAxis; // cone axis in body2 space
|
||||
idVec3 body1Axis; // axis in body1 space that should stay within the cone
|
||||
float cosAngle; // cos( coneAngle / 2 )
|
||||
float sinHalfAngle; // sin( coneAngle / 4 )
|
||||
float cosHalfAngle; // cos( coneAngle / 4 )
|
||||
float epsilon; // lcp epsilon
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
// constrains an axis attached to body1 to be inside a pyramid relative to body2
|
||||
class idAFConstraint_PyramidLimit : public idAFConstraint {
|
||||
|
||||
public:
|
||||
idAFConstraint_PyramidLimit( void );
|
||||
void Setup( idAFBody *b1, idAFBody *b2, const idVec3 &pyramidAnchor,
|
||||
const idVec3 &pyramidAxis, const idVec3 &baseAxis,
|
||||
const float pyramidAngle1, const float pyramidAngle2, const idVec3 &body1Axis );
|
||||
void SetAnchor( const idVec3 &pyramidAxis );
|
||||
void SetBody1Axis( const idVec3 &body1Axis );
|
||||
void SetEpsilon( const float e ) { epsilon = e; }
|
||||
bool Add( idPhysics_AF *phys, float invTimeStep );
|
||||
virtual void DebugDraw( void );
|
||||
virtual void Translate( const idVec3 &translation );
|
||||
virtual void Rotate( const idRotation &rotation );
|
||||
virtual void Save( idSaveGame *saveFile ) const;
|
||||
virtual void Restore( idRestoreGame *saveFile );
|
||||
|
||||
protected:
|
||||
idVec3 pyramidAnchor; // top of the pyramid in body2 space
|
||||
idMat3 pyramidBasis; // pyramid basis in body2 space with base[2] being the pyramid axis
|
||||
idVec3 body1Axis; // axis in body1 space that should stay within the cone
|
||||
float cosAngle[2]; // cos( pyramidAngle / 2 )
|
||||
float sinHalfAngle[2]; // sin( pyramidAngle / 4 )
|
||||
float cosHalfAngle[2]; // cos( pyramidAngle / 4 )
|
||||
float epsilon; // lcp epsilon
|
||||
|
||||
protected:
|
||||
virtual void Evaluate( float invTimeStep );
|
||||
virtual void ApplyFriction( float invTimeStep );
|
||||
};
|
||||
|
||||
|
||||
//===============================================================
|
||||
//
|
||||
// idAFBody
|
||||
//
|
||||
//===============================================================
|
||||
|
||||
typedef struct AFBodyPState_s {
|
||||
idVec3 worldOrigin; // position in world space
|
||||
idMat3 worldAxis; // axis at worldOrigin
|
||||
idVec6 spatialVelocity; // linear and rotational velocity of body
|
||||
idVec6 externalForce; // external force and torque applied to body
|
||||
} AFBodyPState_t;
|
||||
|
||||
|
||||
class idAFBody {
|
||||
|
||||
friend class idPhysics_AF;
|
||||
friend class idAFTree;
|
||||
|
||||
public:
|
||||
idAFBody( void );
|
||||
idAFBody( const idStr &name, idClipModel *clipModel, float density );
|
||||
~idAFBody( void );
|
||||
|
||||
void Init( void );
|
||||
const idStr & GetName( void ) const { return name; }
|
||||
const idVec3 & GetWorldOrigin( void ) const { return current->worldOrigin; }
|
||||
const idMat3 & GetWorldAxis( void ) const { return current->worldAxis; }
|
||||
const idVec3 & GetLinearVelocity( void ) const { return current->spatialVelocity.SubVec3(0); }
|
||||
const idVec3 & GetAngularVelocity( void ) const { return current->spatialVelocity.SubVec3(1); }
|
||||
idVec3 GetPointVelocity( const idVec3 &point ) const;
|
||||
const idVec3 & GetCenterOfMass( void ) const { return centerOfMass; }
|
||||
void SetClipModel( idClipModel *clipModel );
|
||||
idClipModel * GetClipModel( void ) const { return clipModel; }
|
||||
void SetClipMask( const int mask ) { clipMask = mask; fl.clipMaskSet = true; }
|
||||
int GetClipMask( void ) const { return clipMask; }
|
||||
void SetSelfCollision( const bool enable ) { fl.selfCollision = enable; }
|
||||
void SetWorldOrigin( const idVec3 &origin ) { current->worldOrigin = origin; }
|
||||
void SetWorldAxis( const idMat3 &axis ) { current->worldAxis = axis; }
|
||||
void SetLinearVelocity( const idVec3 &linear ) const { current->spatialVelocity.SubVec3(0) = linear; }
|
||||
void SetAngularVelocity( const idVec3 &angular ) const { current->spatialVelocity.SubVec3(1) = angular; }
|
||||
void SetFriction( float linear, float angular, float contact );
|
||||
float GetContactFriction( void ) const { return contactFriction; }
|
||||
void SetBouncyness( float bounce );
|
||||
float GetBouncyness( void ) const { return bouncyness; }
|
||||
void SetDensity( float density, const idMat3 &inertiaScale = mat3_identity );
|
||||
float GetInverseMass( void ) const { return invMass; }
|
||||
idMat3 GetInverseWorldInertia( void ) const { return current->worldAxis.Transpose() * inverseInertiaTensor * current->worldAxis; }
|
||||
|
||||
void SetFrictionDirection( const idVec3 &dir );
|
||||
bool GetFrictionDirection( idVec3 &dir ) const;
|
||||
|
||||
void SetContactMotorDirection( const idVec3 &dir );
|
||||
bool GetContactMotorDirection( idVec3 &dir ) const;
|
||||
void SetContactMotorVelocity( float vel ) { contactMotorVelocity = vel; }
|
||||
float GetContactMotorVelocity( void ) const { return contactMotorVelocity; }
|
||||
void SetContactMotorForce( float force ) { contactMotorForce = force; }
|
||||
float GetContactMotorForce( void ) const { return contactMotorForce; }
|
||||
|
||||
void AddForce( const idVec3 &point, const idVec3 &force );
|
||||
void InverseWorldSpatialInertiaMultiply( idVecX &dst, const float *v ) const;
|
||||
idVec6 & GetResponseForce( int index ) { return reinterpret_cast<idVec6 &>(response[ index * 8 ]); }
|
||||
|
||||
void Save( idSaveGame *saveFile );
|
||||
void Restore( idRestoreGame *saveFile );
|
||||
|
||||
private:
|
||||
// properties
|
||||
idStr name; // name of body
|
||||
idAFBody * parent; // parent of this body
|
||||
idList<idAFBody *> children; // children of this body
|
||||
idClipModel * clipModel; // model used for collision detection
|
||||
idAFConstraint * primaryConstraint; // primary constraint (this->constraint->body1 = this)
|
||||
idList<idAFConstraint *>constraints; // all constraints attached to this body
|
||||
idAFTree * tree; // tree structure this body is part of
|
||||
float linearFriction; // translational friction
|
||||
float angularFriction; // rotational friction
|
||||
float contactFriction; // friction with contact surfaces
|
||||
float bouncyness; // bounce
|
||||
int clipMask; // contents this body collides with
|
||||
idVec3 frictionDir; // specifies a single direction of friction in body space
|
||||
idVec3 contactMotorDir; // contact motor direction
|
||||
float contactMotorVelocity; // contact motor velocity
|
||||
float contactMotorForce; // maximum force applied to reach the motor velocity
|
||||
|
||||
// derived properties
|
||||
float mass; // mass of body
|
||||
float invMass; // inverse mass
|
||||
idVec3 centerOfMass; // center of mass of body
|
||||
idMat3 inertiaTensor; // inertia tensor
|
||||
idMat3 inverseInertiaTensor; // inverse inertia tensor
|
||||
|
||||
// physics state
|
||||
AFBodyPState_t state[2];
|
||||
AFBodyPState_t * current; // current physics state
|
||||
AFBodyPState_t * next; // next physics state
|
||||
AFBodyPState_t saved; // saved physics state
|
||||
idVec3 atRestOrigin; // origin at rest
|
||||
idMat3 atRestAxis; // axis at rest
|
||||
|
||||
// simulation variables used during calculations
|
||||
idMatX inverseWorldSpatialInertia; // inverse spatial inertia in world space
|
||||
idMatX I, invI; // transformed inertia
|
||||
idMatX J; // transformed constraint matrix
|
||||
idVecX s; // temp solution
|
||||
idVecX totalForce; // total force acting on body
|
||||
idVecX auxForce; // force from auxiliary constraints
|
||||
idVecX acceleration; // acceleration
|
||||
float * response; // forces on body in response to auxiliary constraint forces
|
||||
int * responseIndex; // index to response forces
|
||||
int numResponses; // number of response forces
|
||||
int maxAuxiliaryIndex; // largest index of an auxiliary constraint constraining this body
|
||||
int maxSubTreeAuxiliaryIndex; // largest index of an auxiliary constraint constraining this body or one of it's children
|
||||
|
||||
struct bodyFlags_s {
|
||||
bool clipMaskSet : 1; // true if this body has a clip mask set
|
||||
bool selfCollision : 1; // true if this body can collide with other bodies of this AF
|
||||
bool spatialInertiaSparse: 1; // true if the spatial inertia matrix is sparse
|
||||
bool useFrictionDir : 1; // true if a single friction direction should be used
|
||||
bool useContactMotorDir : 1; // true if a contact motor should be used
|
||||
bool isZero : 1; // true if 's' is zero during calculations
|
||||
} fl;
|
||||
};
|
||||
|
||||
|
||||
//===============================================================
|
||||
//
|
||||
// idAFTree
|
||||
//
|
||||
//===============================================================
|
||||
|
||||
class idAFTree {
|
||||
friend class idPhysics_AF;
|
||||
|
||||
public:
|
||||
void Factor( void ) const;
|
||||
void Solve( int auxiliaryIndex = 0 ) const;
|
||||
void Response( const idAFConstraint *constraint, int row, int auxiliaryIndex ) const;
|
||||
void CalculateForces( float timeStep ) const;
|
||||
void SetMaxSubTreeAuxiliaryIndex( void );
|
||||
void SortBodies( void );
|
||||
void SortBodies_r( idList<idAFBody*>&sortedList, idAFBody *body );
|
||||
void DebugDraw( const idVec4 &color ) const;
|
||||
|
||||
private:
|
||||
idList<idAFBody *> sortedBodies;
|
||||
};
|
||||
|
||||
|
||||
//===============================================================
|
||||
//
|
||||
// idPhysics_AF
|
||||
//
|
||||
//===============================================================
|
||||
|
||||
typedef struct AFPState_s {
|
||||
int atRest; // >= 0 if articulated figure is at rest
|
||||
float noMoveTime; // time the articulated figure is hardly moving
|
||||
float activateTime; // time since last activation
|
||||
float lastTimeStep; // last time step
|
||||
idVec6 pushVelocity; // velocity with which the af is pushed
|
||||
} AFPState_t;
|
||||
|
||||
typedef struct AFCollision_s {
|
||||
trace_t trace;
|
||||
idAFBody * body;
|
||||
} AFCollision_t;
|
||||
|
||||
class idPhysics_AF : public idPhysics_Base {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_AF );
|
||||
|
||||
idPhysics_AF( void );
|
||||
~idPhysics_AF( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
// initialisation
|
||||
int AddBody( idAFBody *body ); // returns body id
|
||||
void AddConstraint( idAFConstraint *constraint );
|
||||
void AddFrameConstraint( idAFConstraint *constraint );
|
||||
// force a body to have a certain id
|
||||
void ForceBodyId( idAFBody *body, int newId );
|
||||
// get body or constraint id
|
||||
int GetBodyId( idAFBody *body ) const;
|
||||
int GetBodyId( const char *bodyName ) const;
|
||||
int GetConstraintId( idAFConstraint *constraint ) const;
|
||||
int GetConstraintId( const char *constraintName ) const;
|
||||
// number of bodies and constraints
|
||||
int GetNumBodies( void ) const;
|
||||
int GetNumConstraints( void ) const;
|
||||
// retrieve body or constraint
|
||||
idAFBody * GetBody( const char *bodyName ) const;
|
||||
idAFBody * GetBody( const int id ) const;
|
||||
idAFBody * GetMasterBody( void ) const { return masterBody; }
|
||||
idAFConstraint * GetConstraint( const char *constraintName ) const;
|
||||
idAFConstraint * GetConstraint( const int id ) const;
|
||||
// delete body or constraint
|
||||
void DeleteBody( const char *bodyName );
|
||||
void DeleteBody( const int id );
|
||||
void DeleteConstraint( const char *constraintName );
|
||||
void DeleteConstraint( const int id );
|
||||
|
||||
// get all the contact constraints acting on the body
|
||||
int GetBodyContactConstraints( const int id, idAFConstraint_Contact *contacts[], int maxContacts ) const;
|
||||
// set the default friction for bodies
|
||||
void SetDefaultFriction( float linear, float angular, float contact );
|
||||
// suspend settings
|
||||
void SetSuspendSpeed( const idVec2 &velocity, const idVec2 &acceleration );
|
||||
// set the time and tolerances used to determine if the simulation can be suspended when the figure hardly moves for a while
|
||||
void SetSuspendTolerance( const float noMoveTime, const float translationTolerance, const float rotationTolerance );
|
||||
// set minimum and maximum simulation time in seconds
|
||||
void SetSuspendTime( const float minTime, const float maxTime );
|
||||
// set the time scale value
|
||||
void SetTimeScale( const float ts ) { timeScale = ts; }
|
||||
// set time scale ramp
|
||||
void SetTimeScaleRamp( const float start, const float end );
|
||||
// set the joint friction scale
|
||||
void SetJointFrictionScale( const float scale ) { jointFrictionScale = scale; }
|
||||
// set joint friction dent
|
||||
void SetJointFrictionDent( const float dent, const float start, const float end );
|
||||
// get the current joint friction scale
|
||||
float GetJointFrictionScale( void ) const;
|
||||
// set the contact friction scale
|
||||
void SetContactFrictionScale( const float scale ) { contactFrictionScale = scale; }
|
||||
// set contact friction dent
|
||||
void SetContactFrictionDent( const float dent, const float start, const float end );
|
||||
// get the current contact friction scale
|
||||
float GetContactFrictionScale( void ) const;
|
||||
// enable or disable collision detection
|
||||
void SetCollision( const bool enable ) { enableCollision = enable; }
|
||||
// enable or disable self collision
|
||||
void SetSelfCollision( const bool enable ) { selfCollision = enable; }
|
||||
// enable or disable coming to a dead stop
|
||||
void SetComeToRest( bool enable ) { comeToRest = enable; }
|
||||
// call when structure of articulated figure changes
|
||||
void SetChanged( void ) { changedAF = true; }
|
||||
// RAVEN BEGIN
|
||||
// rjohnson: fast AF eval to skip some things that are not needed for specific circumstances
|
||||
// enable or disable fast evaluation
|
||||
void SetFastEval( const bool enable ) { fastEval = enable; }
|
||||
// RAVEN END
|
||||
// enable/disable activation by impact
|
||||
void EnableImpact( void );
|
||||
void DisableImpact( void );
|
||||
// lock of unlock the world constraints
|
||||
void LockWorldConstraints( const bool lock ) { worldConstraintsLocked = lock; }
|
||||
// set force pushable
|
||||
void SetForcePushable( const bool enable ) { forcePushable = enable; }
|
||||
// update the clip model positions
|
||||
void UpdateClipModels( void );
|
||||
|
||||
public: // common physics interface
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
int GetNumClipModels( void ) const;
|
||||
|
||||
void SetMass( float mass, int id = -1 );
|
||||
float GetMass( int id = -1 ) const;
|
||||
|
||||
//MCG: added SetImpulseThreshold
|
||||
void SetImpulseThreshold( float newIT ) { impulseThreshold = newIT; };
|
||||
|
||||
void SetContents( int contents, int id = -1 );
|
||||
int GetContents( int id = -1 ) const;
|
||||
|
||||
const idBounds & GetBounds( int id = -1 ) const;
|
||||
const idBounds & GetAbsBounds( int id = -1 ) const;
|
||||
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const;
|
||||
void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
|
||||
void AddForce( const int id, const idVec3 &point, const idVec3 &force );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
void Activate( void );
|
||||
void PutToRest( void );
|
||||
bool IsPushable( void ) const;
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
const idVec3 & GetOrigin( int id = 0 ) const;
|
||||
const idMat3 & GetAxis( int id = 0 ) const;
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
void SetAngularVelocity( const idVec3 &newAngularVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
const idVec3 & GetAngularVelocity( int id = 0 ) const;
|
||||
|
||||
void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
|
||||
void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
|
||||
int ClipContents( const idClipModel *model ) const;
|
||||
|
||||
void DisableClip( void );
|
||||
void EnableClip( void );
|
||||
|
||||
void UnlinkClip( void );
|
||||
void LinkClip( void );
|
||||
|
||||
bool EvaluateContacts( void );
|
||||
|
||||
void SetPushed( int deltaTime );
|
||||
const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
|
||||
const idVec3 & GetPushedAngularVelocity( const int id = 0 ) const;
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated = true );
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
private:
|
||||
// articulated figure
|
||||
idList<idAFTree *> trees; // tree structures
|
||||
idList<idAFBody *> bodies; // all bodies
|
||||
idList<idAFConstraint *>constraints; // all frame independent constraints
|
||||
idList<idAFConstraint *>primaryConstraints; // list with primary constraints
|
||||
idList<idAFConstraint *>auxiliaryConstraints; // list with auxiliary constraints
|
||||
idList<idAFConstraint *>frameConstraints; // constraints that only live one frame
|
||||
idList<idAFConstraint_Contact *>contactConstraints; // contact constraints
|
||||
idList<int> contactBodies; // body id for each contact
|
||||
idList<AFCollision_t> collisions; // collisions
|
||||
bool changedAF; // true when the articulated figure just changed
|
||||
|
||||
// properties
|
||||
float linearFriction; // default translational friction
|
||||
float angularFriction; // default rotational friction
|
||||
float contactFriction; // default friction with contact surfaces
|
||||
float bouncyness; // default bouncyness
|
||||
float totalMass; // total mass of articulated figure
|
||||
float forceTotalMass; // force this total mass
|
||||
|
||||
idVec2 suspendVelocity; // simulation may not be suspended if a body has more velocity
|
||||
idVec2 suspendAcceleration; // simulation may not be suspended if a body has more acceleration
|
||||
float noMoveTime; // suspend simulation if hardly any movement for this many seconds
|
||||
float noMoveTranslation; // maximum translation considered no movement
|
||||
float noMoveRotation; // maximum rotation considered no movement
|
||||
float minMoveTime; // if > 0 the simulation is never suspended before running this many seconds
|
||||
float maxMoveTime; // if > 0 the simulation is always suspeded after running this many seconds
|
||||
float impulseThreshold; // threshold below which impulses are ignored to avoid continuous activation
|
||||
|
||||
float timeScale; // the time is scaled with this value for slow motion effects
|
||||
float timeScaleRampStart; // start of time scale change
|
||||
float timeScaleRampEnd; // end of time scale change
|
||||
|
||||
float jointFrictionScale; // joint friction scale
|
||||
float jointFrictionDent; // joint friction dives from 1 to this value and goes up again
|
||||
float jointFrictionDentStart; // start time of joint friction dent
|
||||
float jointFrictionDentEnd; // end time of joint friction dent
|
||||
float jointFrictionDentScale; // dent scale
|
||||
|
||||
float contactFrictionScale; // contact friction scale
|
||||
float contactFrictionDent; // contact friction dives from 1 to this value and goes up again
|
||||
float contactFrictionDentStart; // start time of contact friction dent
|
||||
float contactFrictionDentEnd; // end time of contact friction dent
|
||||
float contactFrictionDentScale; // dent scale
|
||||
|
||||
bool enableCollision; // if true collision detection is enabled
|
||||
bool selfCollision; // if true the self collision is allowed
|
||||
bool comeToRest; // if true the figure can come to rest
|
||||
bool linearTime; // if true use the linear time algorithm
|
||||
bool noImpact; // if true do not activate when another object collides
|
||||
bool worldConstraintsLocked; // if true world constraints cannot be moved
|
||||
bool forcePushable; // if true can be pushed even when bound to a master
|
||||
// RAVEN BEGIN
|
||||
// rjohnson: fast AF eval to skip some things that are not needed for specific circumstances
|
||||
bool fastEval; // if true the fast eval is on
|
||||
// RAVEN END
|
||||
|
||||
// physics state
|
||||
AFPState_t current;
|
||||
AFPState_t saved;
|
||||
|
||||
idAFBody * masterBody; // master body
|
||||
idLCP * lcp; // linear complementarity problem solver
|
||||
|
||||
private:
|
||||
void BuildTrees( void );
|
||||
bool IsClosedLoop( const idAFBody *body1, const idAFBody *body2 ) const;
|
||||
void PrimaryFactor( void );
|
||||
void EvaluateBodies( float timeStep );
|
||||
void EvaluateConstraints( float timeStep );
|
||||
void AddFrameConstraints( void );
|
||||
void RemoveFrameConstraints( void );
|
||||
void ApplyFriction( float timeStep, float endTimeMSec );
|
||||
void PrimaryForces( float timeStep );
|
||||
void AuxiliaryForces( float timeStep );
|
||||
void VerifyContactConstraints( void );
|
||||
void SetupContactConstraints( void );
|
||||
void ApplyContactForces( void );
|
||||
void Evolve( float timeStep );
|
||||
idEntity * SetupCollisionForBody( idAFBody *body ) const;
|
||||
bool CollisionImpulse( float timeStep, idAFBody *body, trace_t &collision );
|
||||
bool ApplyCollisions( float timeStep );
|
||||
void CheckForCollisions( float timeStep );
|
||||
void ClearExternalForce( void );
|
||||
void AddGravity( void );
|
||||
void SwapStates( void );
|
||||
bool TestIfAtRest( float timeStep );
|
||||
void Rest( void );
|
||||
void AddPushVelocity( const idVec6 &pushVelocity );
|
||||
void DebugDraw( void );
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_AF_H__ */
|
||||
@@ -0,0 +1,373 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idPhysics_Base, idPhysics_Actor )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::idPhysics_Actor
|
||||
================
|
||||
*/
|
||||
idPhysics_Actor::idPhysics_Actor( void ) {
|
||||
clipModel = NULL;
|
||||
SetClipModelAxis();
|
||||
mass = 100.0f;
|
||||
invMass = 1.0f / mass;
|
||||
masterEntity = NULL;
|
||||
masterYaw = 0.0f;
|
||||
masterDeltaYaw = 0.0f;
|
||||
groundEntityPtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::~idPhysics_Actor
|
||||
================
|
||||
*/
|
||||
idPhysics_Actor::~idPhysics_Actor( void ) {
|
||||
if ( clipModel ) {
|
||||
delete clipModel;
|
||||
clipModel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::Save
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::Save( idSaveGame *savefile ) const {
|
||||
|
||||
savefile->WriteClipModel( clipModel );
|
||||
savefile->WriteMat3( clipModelAxis );
|
||||
|
||||
savefile->WriteFloat( mass );
|
||||
savefile->WriteFloat( invMass );
|
||||
|
||||
savefile->WriteObject( masterEntity );
|
||||
savefile->WriteFloat( masterYaw );
|
||||
savefile->WriteFloat( masterDeltaYaw );
|
||||
|
||||
groundEntityPtr.Save( savefile );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::Restore
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::Restore( idRestoreGame *savefile ) {
|
||||
|
||||
savefile->ReadClipModel( clipModel );
|
||||
savefile->ReadMat3( clipModelAxis );
|
||||
|
||||
savefile->ReadFloat( mass );
|
||||
savefile->ReadFloat( invMass );
|
||||
|
||||
savefile->ReadObject( reinterpret_cast<idClass *&>( masterEntity ) );
|
||||
savefile->ReadFloat( masterYaw );
|
||||
savefile->ReadFloat( masterDeltaYaw );
|
||||
|
||||
groundEntityPtr.Restore( savefile );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::SetClipModelAxis
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::SetClipModelAxis( void ) {
|
||||
// align clip model to gravity direction
|
||||
if ( ( gravityNormal[2] == -1.0f ) || ( gravityNormal == vec3_zero ) ) {
|
||||
clipModelAxis.Identity();
|
||||
}
|
||||
else {
|
||||
clipModelAxis[2] = -gravityNormal;
|
||||
clipModelAxis[2].NormalVectors( clipModelAxis[0], clipModelAxis[1] );
|
||||
clipModelAxis[1] = -clipModelAxis[1];
|
||||
}
|
||||
|
||||
if ( clipModel ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, clipModel->GetOrigin(), clipModelAxis );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetGravityAxis
|
||||
================
|
||||
*/
|
||||
const idMat3 &idPhysics_Actor::GetGravityAxis( void ) const {
|
||||
return clipModelAxis;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetMasterDeltaYaw
|
||||
================
|
||||
*/
|
||||
float idPhysics_Actor::GetMasterDeltaYaw( void ) const {
|
||||
return masterDeltaYaw;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetGroundEntity
|
||||
================
|
||||
*/
|
||||
idEntity *idPhysics_Actor::GetGroundEntity( void ) const {
|
||||
return groundEntityPtr.GetEntity();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::SetClipModel
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::SetClipModel( idClipModel *model, const float density, int id, bool freeOld ) {
|
||||
assert( self );
|
||||
assert( model ); // a clip model is required
|
||||
assert( model->IsTraceModel() ); // and it should be a trace model
|
||||
assert( density > 0.0f ); // density should be valid
|
||||
|
||||
if ( clipModel && clipModel != model && freeOld ) {
|
||||
delete clipModel;
|
||||
}
|
||||
clipModel = model;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, clipModel->GetOrigin(), clipModelAxis );
|
||||
// RAVEN END
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetClipModel
|
||||
================
|
||||
*/
|
||||
idClipModel *idPhysics_Actor::GetClipModel( int id ) const {
|
||||
return clipModel;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetNumClipModels
|
||||
================
|
||||
*/
|
||||
int idPhysics_Actor::GetNumClipModels( void ) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::SetMass
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::SetMass( float _mass, int id ) {
|
||||
assert( _mass > 0.0f );
|
||||
mass = _mass;
|
||||
invMass = 1.0f / _mass;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetMass
|
||||
================
|
||||
*/
|
||||
float idPhysics_Actor::GetMass( int id ) const {
|
||||
return mass;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::SetContents
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::SetContents( int contents, int id ) {
|
||||
clipModel->SetContents( contents );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetContents
|
||||
================
|
||||
*/
|
||||
int idPhysics_Actor::GetContents( int id ) const {
|
||||
return clipModel->GetContents();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetBounds
|
||||
================
|
||||
*/
|
||||
const idBounds &idPhysics_Actor::GetBounds( int id ) const {
|
||||
return clipModel->GetBounds();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetAbsBounds
|
||||
================
|
||||
*/
|
||||
const idBounds &idPhysics_Actor::GetAbsBounds( int id ) const {
|
||||
return clipModel->GetAbsBounds();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::IsPushable
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Actor::IsPushable( void ) const {
|
||||
return ( masterEntity == NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetOrigin
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Actor::GetOrigin( int id ) const {
|
||||
return clipModel->GetOrigin();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Player::GetAxis
|
||||
================
|
||||
*/
|
||||
const idMat3 &idPhysics_Actor::GetAxis( int id ) const {
|
||||
return clipModel->GetAxis();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::SetGravity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::SetGravity( const idVec3 &newGravity ) {
|
||||
if ( newGravity != gravityVector ) {
|
||||
idPhysics_Base::SetGravity( newGravity );
|
||||
SetClipModelAxis();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::ClipTranslation
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
|
||||
if ( model ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.TranslationModel( self, results, clipModel->GetOrigin(), clipModel->GetOrigin() + translation,
|
||||
clipModel, clipModel->GetAxis(), clipMask,
|
||||
model->GetCollisionModel(), model->GetOrigin(), model->GetAxis() );
|
||||
}
|
||||
else {
|
||||
gameLocal.Translation( self, results, clipModel->GetOrigin(), clipModel->GetOrigin() + translation,
|
||||
clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::ClipRotation
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
|
||||
if ( model ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.RotationModel( self, results, clipModel->GetOrigin(), rotation,
|
||||
clipModel, clipModel->GetAxis(), clipMask,
|
||||
model->GetCollisionModel(), model->GetOrigin(), model->GetAxis() );
|
||||
}
|
||||
else {
|
||||
gameLocal.Rotation( self, results, clipModel->GetOrigin(), rotation,
|
||||
clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::ClipContents
|
||||
================
|
||||
*/
|
||||
int idPhysics_Actor::ClipContents( const idClipModel *model ) const {
|
||||
if ( model ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip models
|
||||
return gameLocal.ContentsModel( self, clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1,
|
||||
model->GetCollisionModel(), model->GetOrigin(), model->GetAxis() );
|
||||
}
|
||||
else {
|
||||
return gameLocal.Contents( self, clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1, NULL );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::DisableClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::DisableClip( void ) {
|
||||
clipModel->Disable();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::EnableClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::EnableClip( void ) {
|
||||
clipModel->Enable();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::UnlinkClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::UnlinkClip( void ) {
|
||||
clipModel->Unlink();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::LinkClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Actor::LinkClip( void ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, clipModel->GetOrigin(), clipModel->GetAxis() );
|
||||
// RAVEN END
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::EvaluateContacts
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Actor::EvaluateContacts( void ) {
|
||||
|
||||
// get all the ground contacts
|
||||
ClearContacts();
|
||||
AddGroundContacts( clipModel );
|
||||
AddContactEntitiesForContacts();
|
||||
|
||||
return ( contacts.Num() != 0 );
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
|
||||
#ifndef __PHYSICS_ACTOR_H__
|
||||
#define __PHYSICS_ACTOR_H__
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
Actor physics base class
|
||||
|
||||
An actor typically uses one collision model which is aligned with the gravity
|
||||
direction. The collision model is usually a simple box with the origin at the
|
||||
bottom center.
|
||||
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
class idPhysics_Actor : public idPhysics_Base {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_Actor );
|
||||
|
||||
idPhysics_Actor( void );
|
||||
~idPhysics_Actor( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
// get delta yaw of master
|
||||
float GetMasterDeltaYaw( void ) const;
|
||||
// returns the ground entity
|
||||
idEntity * GetGroundEntity( void ) const;
|
||||
// align the clip model with the gravity direction
|
||||
void SetClipModelAxis( void );
|
||||
|
||||
public: // common physics interface
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
int GetNumClipModels( void ) const;
|
||||
|
||||
void SetMass( float mass, int id = -1 );
|
||||
float GetMass( int id = -1 ) const;
|
||||
|
||||
void SetContents( int contents, int id = -1 );
|
||||
int GetContents( int id = -1 ) const;
|
||||
|
||||
const idBounds & GetBounds( int id = -1 ) const;
|
||||
const idBounds & GetAbsBounds( int id = -1 ) const;
|
||||
|
||||
bool IsPushable( void ) const;
|
||||
|
||||
const idVec3 & GetOrigin( int id = 0 ) const;
|
||||
const idMat3 & GetAxis( int id = 0 ) const;
|
||||
|
||||
void SetGravity( const idVec3 &newGravity );
|
||||
// RAVEN BEGIN
|
||||
// abahr: made virtual
|
||||
virtual const idMat3& GetGravityAxis( void ) const;
|
||||
// RAVEN END
|
||||
|
||||
void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
|
||||
void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
|
||||
int ClipContents( const idClipModel *model ) const;
|
||||
|
||||
void DisableClip( void );
|
||||
void EnableClip( void );
|
||||
|
||||
void UnlinkClip( void );
|
||||
void LinkClip( void );
|
||||
|
||||
bool EvaluateContacts( void );
|
||||
|
||||
protected:
|
||||
idClipModel * clipModel; // clip model used for collision detection
|
||||
idMat3 clipModelAxis; // axis of clip model aligned with gravity direction
|
||||
|
||||
// derived properties
|
||||
float mass;
|
||||
float invMass;
|
||||
|
||||
// master
|
||||
idEntity * masterEntity;
|
||||
float masterYaw;
|
||||
float masterDeltaYaw;
|
||||
|
||||
// results of last evaluate
|
||||
idEntityPtr<idEntity> groundEntityPtr;
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_ACTOR_H__ */
|
||||
@@ -0,0 +1,872 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idPhysics, idPhysics_Base )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::idPhysics_Base
|
||||
================
|
||||
*/
|
||||
idPhysics_Base::idPhysics_Base( void ) {
|
||||
self = NULL;
|
||||
clipMask = 0;
|
||||
SetGravity( gameLocal.GetGravity() );
|
||||
ClearContacts();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::~idPhysics_Base
|
||||
================
|
||||
*/
|
||||
idPhysics_Base::~idPhysics_Base( void ) {
|
||||
if ( self && self->GetPhysics() == this ) {
|
||||
self->SetPhysics( NULL );
|
||||
}
|
||||
idForce::DeletePhysics( this );
|
||||
ClearContacts();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::Save
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::Save( idSaveGame *savefile ) const {
|
||||
int i;
|
||||
|
||||
savefile->WriteObject( self );
|
||||
savefile->WriteInt( clipMask );
|
||||
savefile->WriteVec3( gravityVector );
|
||||
savefile->WriteVec3( gravityNormal );
|
||||
|
||||
savefile->WriteInt( contacts.Num() );
|
||||
for ( i = 0; i < contacts.Num(); i++ ) {
|
||||
savefile->WriteContactInfo( contacts[i] );
|
||||
}
|
||||
|
||||
savefile->WriteInt( contactEntities.Num() );
|
||||
for ( i = 0; i < contactEntities.Num(); i++ ) {
|
||||
contactEntities[i].Save( savefile );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::Restore
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::Restore( idRestoreGame *savefile ) {
|
||||
int i, num;
|
||||
|
||||
savefile->ReadObject( reinterpret_cast<idClass *&>( self ) );
|
||||
savefile->ReadInt( clipMask );
|
||||
savefile->ReadVec3( gravityVector );
|
||||
savefile->ReadVec3( gravityNormal );
|
||||
|
||||
savefile->ReadInt( num );
|
||||
contacts.SetNum( num );
|
||||
for ( i = 0; i < contacts.Num(); i++ ) {
|
||||
savefile->ReadContactInfo( contacts[i] );
|
||||
}
|
||||
|
||||
savefile->ReadInt( num );
|
||||
contactEntities.SetNum( num );
|
||||
for ( i = 0; i < contactEntities.Num(); i++ ) {
|
||||
contactEntities[i].Restore( savefile );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetSelf
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetSelf( idEntity *e ) {
|
||||
assert( e );
|
||||
self = e;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetClipModel
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetClipModel( idClipModel *model, float density, int id, bool freeOld ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetClipModel
|
||||
================
|
||||
*/
|
||||
idClipModel *idPhysics_Base::GetClipModel( int id ) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetNumClipModels
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::GetNumClipModels( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetMass
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetMass( float mass, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetMass
|
||||
================
|
||||
*/
|
||||
float idPhysics_Base::GetMass( int id ) const {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: Added center mass call
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetCenterMass
|
||||
|
||||
default center of mass is origin
|
||||
================
|
||||
*/
|
||||
idVec3 idPhysics_Base::GetCenterMass ( int id ) const {
|
||||
return GetOrigin();
|
||||
}
|
||||
// RAVEN END
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetContents
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetContents( int contents, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetClipMask
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::GetContents( int id ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetClipMask
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetClipMask( int mask, int id ) {
|
||||
clipMask = mask;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetClipMask
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::GetClipMask( int id ) const {
|
||||
return clipMask;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetBounds
|
||||
================
|
||||
*/
|
||||
const idBounds &idPhysics_Base::GetBounds( int id ) const {
|
||||
return bounds_zero;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetAbsBounds
|
||||
================
|
||||
*/
|
||||
const idBounds &idPhysics_Base::GetAbsBounds( int id ) const {
|
||||
return bounds_zero;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::Evaluate
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Base::Evaluate( int timeStepMSec, int endTimeMSec ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::UpdateTime
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::UpdateTime( int endTimeMSec ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::GetTime( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetImpactInfo
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
|
||||
memset( info, 0, sizeof( *info ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::ApplyImpulse
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::AddForce
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::AddForce( const int id, const idVec3 &point, const idVec3 &force ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::Activate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::Activate( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::PutToRest
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::PutToRest( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::IsAtRest
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Base::IsAtRest( void ) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetRestStartTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::GetRestStartTime( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::IsPushable
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Base::IsPushable( void ) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: water interraction
|
||||
bool idPhysics_Base::IsInWater ( void ) const {
|
||||
return false;
|
||||
}
|
||||
// RAVEN END
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SaveState
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SaveState( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::RestoreState
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::RestoreState( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetOrigin
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetOrigin( const idVec3 &newOrigin, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetAxis
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetAxis( const idMat3 &newAxis, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::Translate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::Translate( const idVec3 &translation, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::Rotate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::Rotate( const idRotation &rotation, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetOrigin
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Base::GetOrigin( int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetAxis
|
||||
================
|
||||
*/
|
||||
const idMat3 &idPhysics_Base::GetAxis( int id ) const {
|
||||
return mat3_identity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetLinearVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetAngularVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetLinearVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Base::GetLinearVelocity( int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetAngularVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Base::GetAngularVelocity( int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetGravity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetGravity( const idVec3 &newGravity ) {
|
||||
gravityVector = newGravity;
|
||||
gravityNormal = newGravity;
|
||||
gravityNormal.Normalize();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetGravity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Base::GetGravity( void ) const {
|
||||
return gravityVector;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetGravityNormal
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Base::GetGravityNormal( void ) const {
|
||||
return gravityNormal;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::ClipTranslation
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
|
||||
memset( &results, 0, sizeof( trace_t ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::ClipRotation
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
|
||||
memset( &results, 0, sizeof( trace_t ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::ClipContents
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::ClipContents( const idClipModel *model ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::DisableClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::DisableClip( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::EnableClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::EnableClip( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::UnlinkClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::UnlinkClip( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::LinkClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::LinkClip( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::EvaluateContacts
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Base::EvaluateContacts( void ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetNumContacts
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::GetNumContacts( void ) const {
|
||||
return contacts.Num();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetContact
|
||||
================
|
||||
*/
|
||||
const contactInfo_t &idPhysics_Base::GetContact( int num ) const {
|
||||
return contacts[num];
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::ClearContacts
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::ClearContacts( void ) {
|
||||
int i;
|
||||
idEntity *ent;
|
||||
|
||||
for ( i = 0; i < contacts.Num(); i++ ) {
|
||||
ent = gameLocal.entities[ contacts[i].entityNum ];
|
||||
if ( ent ) {
|
||||
ent->RemoveContactEntity( self );
|
||||
}
|
||||
}
|
||||
contacts.SetNum( 0, false );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::AddContactEntity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::AddContactEntity( idEntity *e ) {
|
||||
int i;
|
||||
idEntity *ent;
|
||||
bool found = false;
|
||||
|
||||
for ( i = 0; i < contactEntities.Num(); i++ ) {
|
||||
ent = contactEntities[i].GetEntity();
|
||||
if ( ent == NULL ) {
|
||||
contactEntities.RemoveIndex( i-- );
|
||||
}
|
||||
if ( ent == e ) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if ( !found ) {
|
||||
contactEntities.Alloc() = e;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::RemoveContactEntity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::RemoveContactEntity( idEntity *e ) {
|
||||
int i;
|
||||
idEntity *ent;
|
||||
|
||||
for ( i = 0; i < contactEntities.Num(); i++ ) {
|
||||
ent = contactEntities[i].GetEntity();
|
||||
if ( !ent ) {
|
||||
contactEntities.RemoveIndex( i-- );
|
||||
continue;
|
||||
}
|
||||
if ( ent == e ) {
|
||||
contactEntities.RemoveIndex( i-- );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// abahr:
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetContactNormal
|
||||
================
|
||||
*/
|
||||
const idVec3 idPhysics_Base::GetContactNormal() const {
|
||||
idVec3 normal( vec3_zero );
|
||||
|
||||
for( int ix = 0; ix < GetNumContacts(); ++ix ) {
|
||||
normal += GetContact( ix ).normal;
|
||||
}
|
||||
|
||||
return normal.ToNormal();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetContactNormal
|
||||
================
|
||||
*/
|
||||
const idVec3 idPhysics_Base::GetGroundContactNormal() const {
|
||||
idVec3 normal( vec3_zero );
|
||||
|
||||
for( int ix = 0; ix < GetNumContacts(); ++ix ) {
|
||||
if ( GetContact(ix).normal * -gravityNormal > 0.0f ) {
|
||||
normal += GetContact( ix ).normal;
|
||||
}
|
||||
}
|
||||
|
||||
return normal.ToNormal();
|
||||
}
|
||||
// RAVEN END
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::HasGroundContacts
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Base::HasGroundContacts( void ) const {
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < contacts.Num(); i++ ) {
|
||||
if ( contacts[i].normal * -gravityNormal > 0.0f ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::IsGroundEntity
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Base::IsGroundEntity( int entityNum ) const {
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < contacts.Num(); i++ ) {
|
||||
if ( contacts[i].entityNum == entityNum && ( contacts[i].normal * -gravityNormal > 0.0f ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::IsGroundClipModel
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Base::IsGroundClipModel( int entityNum, int id ) const {
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < contacts.Num(); i++ ) {
|
||||
if ( contacts[i].entityNum == entityNum && contacts[i].id == id && ( contacts[i].normal * -gravityNormal > 0.0f ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetPushed
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetPushed( int deltaTime ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetPushedLinearVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Base::GetPushedLinearVelocity( const int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetPushedAngularVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Base::GetPushedAngularVelocity( const int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetMaster
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetMaster( idEntity *master, const bool orientated ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetBlockingInfo
|
||||
================
|
||||
*/
|
||||
const trace_t *idPhysics_Base::GetBlockingInfo( void ) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetBlockingEntity
|
||||
================
|
||||
*/
|
||||
idEntity *idPhysics_Base::GetBlockingEntity( void ) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetLinearEndTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::GetLinearEndTime( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetAngularEndTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Base::GetAngularEndTime( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::AddGroundContacts
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::AddGroundContacts( const idClipModel *clipModel ) {
|
||||
idVec6 dir;
|
||||
int index, num;
|
||||
|
||||
index = contacts.Num();
|
||||
contacts.SetNum( index + 10, false );
|
||||
|
||||
dir.SubVec3(0) = gravityNormal;
|
||||
dir.SubVec3(1) = vec3_origin;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
num = gameLocal.Contacts( self, &contacts[index], 10, clipModel->GetOrigin(),
|
||||
dir, CONTACT_EPSILON, clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
contacts.SetNum( index + num, false );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::AddContactEntitiesForContacts
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::AddContactEntitiesForContacts( void ) {
|
||||
int i;
|
||||
idEntity *ent;
|
||||
|
||||
for ( i = 0; i < contacts.Num(); i++ ) {
|
||||
ent = gameLocal.entities[ contacts[i].entityNum ];
|
||||
if ( ent && ent != self ) {
|
||||
ent->AddContactEntity( self );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::ActivateContactEntities
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::ActivateContactEntities( void ) {
|
||||
int i;
|
||||
idEntity *ent;
|
||||
|
||||
for ( i = 0; i < contactEntities.Num(); i++ ) {
|
||||
ent = contactEntities[i].GetEntity();
|
||||
if ( ent ) {
|
||||
ent->ActivatePhysics( self );
|
||||
} else {
|
||||
contactEntities.RemoveIndex( i-- );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::IsOutsideWorld
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Base::IsOutsideWorld( void ) const {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
if ( !gameLocal.GetWorldBounds( self ).Expand( 128.0f ).IntersectsBounds( GetAbsBounds() ) ) {
|
||||
// RAVEN END
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::DrawVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::DrawVelocity( int id, float linearScale, float angularScale ) const {
|
||||
idVec3 dir, org, vec, start, end;
|
||||
idMat3 axis;
|
||||
float length, a;
|
||||
|
||||
dir = GetLinearVelocity( id );
|
||||
dir *= linearScale;
|
||||
if ( dir.LengthSqr() > Square( 0.1f ) ) {
|
||||
dir.Truncate( 10.0f );
|
||||
org = GetOrigin( id );
|
||||
gameRenderWorld->DebugArrow( colorRed, org, org + dir, 1 );
|
||||
}
|
||||
|
||||
dir = GetAngularVelocity( id );
|
||||
length = dir.Normalize();
|
||||
length *= angularScale;
|
||||
if ( length > 0.1f ) {
|
||||
if ( length < 60.0f ) {
|
||||
length = 60.0f;
|
||||
}
|
||||
else if ( length > 360.0f ) {
|
||||
length = 360.0f;
|
||||
}
|
||||
axis = GetAxis( id );
|
||||
vec = axis[2];
|
||||
if ( idMath::Fabs( dir * vec ) > 0.99f ) {
|
||||
vec = axis[0];
|
||||
}
|
||||
vec -= vec * dir * vec;
|
||||
vec.Normalize();
|
||||
vec *= 4.0f;
|
||||
start = org + vec;
|
||||
for ( a = 20.0f; a < length; a += 20.0f ) {
|
||||
end = org + idRotation( vec3_origin, dir, -a ).ToMat3() * vec;
|
||||
gameRenderWorld->DebugLine( colorBlue, start, end, 1 );
|
||||
start = end;
|
||||
}
|
||||
end = org + idRotation( vec3_origin, dir, -length ).ToMat3() * vec;
|
||||
gameRenderWorld->DebugArrow( colorBlue, start, end, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::WriteToSnapshot
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::WriteToSnapshot( idBitMsgDelta &msg ) const {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::ReadFromSnapshot
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
|
||||
#ifndef __PHYSICS_BASE_H__
|
||||
#define __PHYSICS_BASE_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Physics base for a moving object using one or more collision models.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
// RAVEN BEGIN
|
||||
// jnewquist: Changed from #define to typedef to fix compiler issues
|
||||
typedef idEntityPtr<idEntity> contactEntity_t;
|
||||
// RAVEN END
|
||||
|
||||
class idPhysics_Base : public idPhysics {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_Base );
|
||||
|
||||
idPhysics_Base( void );
|
||||
~idPhysics_Base( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
public: // common physics interface
|
||||
|
||||
void SetSelf( idEntity *e );
|
||||
//RAVEN BEGIN
|
||||
// abahr: for gravity
|
||||
virtual idEntity* GetSelf() const { return self; }
|
||||
// RAVEN END
|
||||
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
int GetNumClipModels( void ) const;
|
||||
|
||||
void SetMass( float mass, int id = -1 );
|
||||
float GetMass( int id = -1 ) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: added center mass
|
||||
idVec3 GetCenterMass ( int id = -1 ) const;
|
||||
// RAVEN END
|
||||
|
||||
void SetContents( int contents, int id = -1 );
|
||||
int GetContents( int id = -1 ) const;
|
||||
|
||||
void SetClipMask( int mask, int id = -1 );
|
||||
int GetClipMask( int id = -1 ) const;
|
||||
|
||||
const idBounds & GetBounds( int id = -1 ) const;
|
||||
const idBounds & GetAbsBounds( int id = -1 ) const;
|
||||
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const;
|
||||
void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
|
||||
void AddForce( const int id, const idVec3 &point, const idVec3 &force );
|
||||
void Activate( void );
|
||||
void PutToRest( void );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
bool IsPushable( void ) const;
|
||||
// RAVEN BEGIN
|
||||
// bdube: water interraction
|
||||
bool IsInWater ( void ) const;
|
||||
// RAVEN END
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
const idVec3 & GetOrigin( int id = 0 ) const;
|
||||
const idMat3 & GetAxis( int id = 0 ) const;
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
void SetAngularVelocity( const idVec3 &newAngularVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
const idVec3 & GetAngularVelocity( int id = 0 ) const;
|
||||
|
||||
void SetGravity( const idVec3 &newGravity );
|
||||
const idVec3 & GetGravity( void ) const;
|
||||
const idVec3 & GetGravityNormal( void ) const;
|
||||
|
||||
void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
|
||||
void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
|
||||
int ClipContents( const idClipModel *model ) const;
|
||||
|
||||
void DisableClip( void );
|
||||
void EnableClip( void );
|
||||
|
||||
void UnlinkClip( void );
|
||||
void LinkClip( void );
|
||||
|
||||
bool EvaluateContacts( void );
|
||||
int GetNumContacts( void ) const;
|
||||
const contactInfo_t & GetContact( int num ) const;
|
||||
void ClearContacts( void );
|
||||
void AddContactEntity( idEntity *e );
|
||||
void RemoveContactEntity( idEntity *e );
|
||||
|
||||
// RAVEN BEGIN
|
||||
// abahr: helper function used in projectiles
|
||||
virtual const idVec3 GetContactNormal() const;
|
||||
virtual const idVec3 GetGroundContactNormal() const;
|
||||
// RAVEN END
|
||||
|
||||
bool HasGroundContacts( void ) const;
|
||||
bool IsGroundEntity( int entityNum ) const;
|
||||
bool IsGroundClipModel( int entityNum, int id ) const;
|
||||
|
||||
void SetPushed( int deltaTime );
|
||||
const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
|
||||
const idVec3 & GetPushedAngularVelocity( const int id = 0 ) const;
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated = true );
|
||||
|
||||
const trace_t * GetBlockingInfo( void ) const;
|
||||
idEntity * GetBlockingEntity( void ) const;
|
||||
|
||||
int GetLinearEndTime( void ) const;
|
||||
int GetAngularEndTime( void ) const;
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
protected:
|
||||
idEntity * self; // entity using this physics object
|
||||
int clipMask; // contents the physics object collides with
|
||||
idVec3 gravityVector; // direction and magnitude of gravity
|
||||
idVec3 gravityNormal; // normalized direction of gravity
|
||||
idList<contactInfo_t> contacts; // contacts with other physics objects
|
||||
idList<contactEntity_t> contactEntities; // entities touching this physics object
|
||||
|
||||
protected:
|
||||
// add ground contacts for the clip model
|
||||
void AddGroundContacts( const idClipModel *clipModel );
|
||||
// add contact entity links to contact entities
|
||||
void AddContactEntitiesForContacts( void );
|
||||
// active all contact entities
|
||||
void ActivateContactEntities( void );
|
||||
// returns true if the whole physics object is outside the world bounds
|
||||
bool IsOutsideWorld( void ) const;
|
||||
// draw linear and angular velocity
|
||||
void DrawVelocity( int id, float linearScale, float angularScale ) const;
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_BASE_H__ */
|
||||
@@ -0,0 +1,838 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idPhysics_Actor, idPhysics_Monster )
|
||||
END_CLASS
|
||||
|
||||
const float OVERCLIP = 1.001f;
|
||||
|
||||
/*
|
||||
=====================
|
||||
idPhysics_Monster::CheckGround
|
||||
=====================
|
||||
*/
|
||||
void idPhysics_Monster::CheckGround( monsterPState_t &state ) {
|
||||
trace_t groundTrace;
|
||||
idVec3 down;
|
||||
|
||||
if ( gravityNormal == vec3_zero ) {
|
||||
state.onGround = false;
|
||||
groundEntityPtr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
down = state.origin + gravityNormal * CONTACT_EPSILON;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.Translation( self, groundTrace, state.origin, down, clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
|
||||
if ( groundTrace.fraction == 1.0f ) {
|
||||
state.onGround = false;
|
||||
groundEntityPtr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
groundEntityPtr = gameLocal.entities[ groundTrace.c.entityNum ];
|
||||
|
||||
if ( ( groundTrace.c.normal * -gravityNormal ) < minFloorCosine ) {
|
||||
state.onGround = false;
|
||||
return;
|
||||
}
|
||||
|
||||
state.onGround = true;
|
||||
|
||||
// let the entity know about the collision
|
||||
self->Collide( groundTrace, state.velocity );
|
||||
|
||||
// apply impact to a non world floor entity
|
||||
if ( groundTrace.c.entityNum != ENTITYNUM_WORLD && groundEntityPtr.GetEntity() ) {
|
||||
impactInfo_t info;
|
||||
groundEntityPtr.GetEntity()->GetImpactInfo( self, groundTrace.c.id, groundTrace.c.point, &info );
|
||||
if ( info.invMass != 0.0f ) {
|
||||
groundEntityPtr.GetEntity()->ApplyImpulse( self, 0, groundTrace.c.point, state.velocity / ( info.invMass * 10.0f ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idPhysics_Monster::SlideMove
|
||||
=====================
|
||||
*/
|
||||
monsterMoveResult_t idPhysics_Monster::SlideMove( idVec3 &start, idVec3 &velocity, const idVec3 &delta ) {
|
||||
int i;
|
||||
trace_t tr;
|
||||
idVec3 move;
|
||||
|
||||
blockingEntity = NULL;
|
||||
move = delta;
|
||||
for( i = 0; i < 3; i++ ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple collision worlds
|
||||
gameLocal.Translation( self, tr, start, start + move, clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
|
||||
start = tr.endpos;
|
||||
|
||||
if ( tr.fraction == 1.0f ) {
|
||||
if ( i > 0 ) {
|
||||
return MM_SLIDING;
|
||||
}
|
||||
return MM_OK;
|
||||
}
|
||||
|
||||
if ( tr.c.entityNum != ENTITYNUM_NONE ) {
|
||||
blockingEntity = gameLocal.entities[ tr.c.entityNum ];
|
||||
}
|
||||
|
||||
// clip the movement delta and velocity
|
||||
move.ProjectOntoPlane( tr.c.normal, OVERCLIP );
|
||||
velocity.ProjectOntoPlane( tr.c.normal, OVERCLIP );
|
||||
}
|
||||
|
||||
return MM_BLOCKED;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idPhysics_Monster::StepMove
|
||||
|
||||
move start into the delta direction
|
||||
the velocity is clipped conform any collisions
|
||||
=====================
|
||||
*/
|
||||
monsterMoveResult_t idPhysics_Monster::StepMove( idVec3 &start, idVec3 &velocity, const idVec3 &delta ) {
|
||||
trace_t tr;
|
||||
idVec3 up, down, noStepPos, noStepVel, stepPos, stepVel;
|
||||
monsterMoveResult_t result1, result2;
|
||||
float stepdist;
|
||||
float nostepdist;
|
||||
|
||||
if ( delta == vec3_origin ) {
|
||||
return MM_OK;
|
||||
}
|
||||
|
||||
// try to move without stepping up
|
||||
noStepPos = start;
|
||||
noStepVel = velocity;
|
||||
result1 = SlideMove( noStepPos, noStepVel, delta );
|
||||
if ( result1 == MM_OK ) {
|
||||
velocity = noStepVel;
|
||||
// RAVEN BEGIN
|
||||
// bdube: dont step when there is no gravity
|
||||
if ( gravityNormal == vec3_zero || forceDeltaMove ) {
|
||||
// RAVEN END
|
||||
start = noStepPos;
|
||||
return MM_OK;
|
||||
}
|
||||
|
||||
// try to step down so that we walk down slopes and stairs at a normal rate
|
||||
down = noStepPos + gravityNormal * maxStepHeight;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.Translation( self, tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
if ( tr.fraction < 1.0f ) {
|
||||
start = tr.endpos;
|
||||
return MM_STEPPED;
|
||||
} else {
|
||||
start = noStepPos;
|
||||
return MM_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// jnewquist: Use accessor for static class type
|
||||
if ( blockingEntity && blockingEntity->IsType( idActor::GetClassType() ) ) {
|
||||
// RAVEN END
|
||||
// try to step down in case walking into an actor while going down steps
|
||||
down = noStepPos + gravityNormal * maxStepHeight;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.Translation( self, tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
start = tr.endpos;
|
||||
velocity = noStepVel;
|
||||
return MM_BLOCKED;
|
||||
}
|
||||
|
||||
if ( gravityNormal == vec3_zero ) {
|
||||
return result1;
|
||||
}
|
||||
|
||||
// try to step up
|
||||
up = start - gravityNormal * maxStepHeight;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.Translation( self, tr, start, up, clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
if ( tr.fraction == 0.0f ) {
|
||||
start = noStepPos;
|
||||
velocity = noStepVel;
|
||||
return result1;
|
||||
}
|
||||
|
||||
// try to move at the stepped up position
|
||||
stepPos = tr.endpos;
|
||||
stepVel = velocity;
|
||||
result2 = SlideMove( stepPos, stepVel, delta );
|
||||
if ( result2 == MM_BLOCKED ) {
|
||||
start = noStepPos;
|
||||
velocity = noStepVel;
|
||||
return result1;
|
||||
}
|
||||
|
||||
// step down again
|
||||
down = stepPos + gravityNormal * maxStepHeight;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.Translation( self, tr, stepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
|
||||
// RAVEN END
|
||||
stepPos = tr.endpos;
|
||||
|
||||
// if the move is further without stepping up, or the slope is too steap, don't step up
|
||||
nostepdist = ( noStepPos - start ).LengthSqr();
|
||||
stepdist = ( stepPos - start ).LengthSqr();
|
||||
if ( ( nostepdist >= stepdist ) || ( ( tr.c.normal * -gravityNormal ) < minFloorCosine ) ) {
|
||||
start = noStepPos;
|
||||
velocity = noStepVel;
|
||||
return MM_SLIDING;
|
||||
}
|
||||
|
||||
start = stepPos;
|
||||
velocity = stepVel;
|
||||
|
||||
return MM_STEPPED;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::Activate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::Activate( void ) {
|
||||
current.atRest = -1;
|
||||
self->BecomeActive( TH_PHYSICS );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::Rest
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::Rest( void ) {
|
||||
current.atRest = gameLocal.time;
|
||||
current.velocity.Zero();
|
||||
self->BecomeInactive( TH_PHYSICS );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::PutToRest
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::PutToRest( void ) {
|
||||
Rest();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::idPhysics_Monster
|
||||
================
|
||||
*/
|
||||
idPhysics_Monster::idPhysics_Monster( void ) {
|
||||
|
||||
memset( ¤t, 0, sizeof( current ) );
|
||||
current.atRest = -1;
|
||||
saved = current;
|
||||
|
||||
delta.Zero();
|
||||
maxStepHeight = 18.0f;
|
||||
minFloorCosine = 0.7f;
|
||||
moveResult = MM_OK;
|
||||
forceDeltaMove = false;
|
||||
fly = false;
|
||||
useVelocityMove = false;
|
||||
noImpact = false;
|
||||
blockingEntity = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster_SavePState
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster_SavePState( idSaveGame *savefile, const monsterPState_t &state ) {
|
||||
savefile->WriteInt( state.atRest );
|
||||
savefile->WriteBool( state.onGround );
|
||||
savefile->WriteVec3( state.origin );
|
||||
savefile->WriteVec3( state.velocity );
|
||||
savefile->WriteVec3( state.localOrigin );
|
||||
savefile->WriteVec3( state.pushVelocity );
|
||||
|
||||
savefile->WriteVec3( state.lastPushVelocity ); // cnicholson: Added unsaved var
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster_RestorePState
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster_RestorePState( idRestoreGame *savefile, monsterPState_t &state ) {
|
||||
savefile->ReadInt( state.atRest );
|
||||
savefile->ReadBool( state.onGround );
|
||||
savefile->ReadVec3( state.origin );
|
||||
savefile->ReadVec3( state.velocity );
|
||||
savefile->ReadVec3( state.localOrigin );
|
||||
savefile->ReadVec3( state.pushVelocity );
|
||||
|
||||
savefile->ReadVec3( state.lastPushVelocity ); // cnicholson: Added unrestored var
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::Save
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::Save( idSaveGame *savefile ) const {
|
||||
|
||||
idPhysics_Monster_SavePState( savefile, current );
|
||||
idPhysics_Monster_SavePState( savefile, saved );
|
||||
|
||||
savefile->WriteFloat( maxStepHeight );
|
||||
savefile->WriteFloat( minFloorCosine );
|
||||
savefile->WriteVec3( delta );
|
||||
|
||||
savefile->WriteBool( forceDeltaMove );
|
||||
savefile->WriteBool( fly );
|
||||
savefile->WriteBool( useVelocityMove );
|
||||
savefile->WriteBool( noImpact );
|
||||
|
||||
savefile->WriteInt( (int)moveResult );
|
||||
savefile->WriteObject( blockingEntity );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::Restore
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::Restore( idRestoreGame *savefile ) {
|
||||
|
||||
idPhysics_Monster_RestorePState( savefile, current );
|
||||
idPhysics_Monster_RestorePState( savefile, saved );
|
||||
|
||||
savefile->ReadFloat( maxStepHeight );
|
||||
savefile->ReadFloat( minFloorCosine );
|
||||
savefile->ReadVec3( delta );
|
||||
|
||||
savefile->ReadBool( forceDeltaMove );
|
||||
savefile->ReadBool( fly );
|
||||
savefile->ReadBool( useVelocityMove );
|
||||
savefile->ReadBool( noImpact );
|
||||
|
||||
savefile->ReadInt( (int &)moveResult );
|
||||
savefile->ReadObject( reinterpret_cast<idClass *&>( blockingEntity ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::SetDelta
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::SetDelta( const idVec3 &d ) {
|
||||
delta = d;
|
||||
if ( delta != vec3_origin ) {
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::SetMaxStepHeight
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::SetMaxStepHeight( const float newMaxStepHeight ) {
|
||||
maxStepHeight = newMaxStepHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::GetMaxStepHeight
|
||||
================
|
||||
*/
|
||||
float idPhysics_Monster::GetMaxStepHeight( void ) const {
|
||||
return maxStepHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::OnGround
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Monster::OnGround( void ) const {
|
||||
return current.onGround;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::GetSlideMoveEntity
|
||||
================
|
||||
*/
|
||||
idEntity *idPhysics_Monster::GetSlideMoveEntity( void ) const {
|
||||
return blockingEntity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::GetMoveResult
|
||||
================
|
||||
*/
|
||||
monsterMoveResult_t idPhysics_Monster::GetMoveResult( void ) const {
|
||||
return moveResult;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::ForceDeltaMove
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::ForceDeltaMove( bool force ) {
|
||||
forceDeltaMove = force;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::UseFlyMove
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::UseFlyMove( bool force ) {
|
||||
fly = force;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::UseVelocityMove
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::UseVelocityMove( bool force ) {
|
||||
useVelocityMove = force;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::EnableImpact
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::EnableImpact( void ) {
|
||||
noImpact = false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::DisableImpact
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::DisableImpact( void ) {
|
||||
noImpact = true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::Evaluate
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Monster::Evaluate( int timeStepMSec, int endTimeMSec ) {
|
||||
idVec3 masterOrigin, oldOrigin;
|
||||
idMat3 masterAxis;
|
||||
float timeStep;
|
||||
|
||||
timeStep = MS2SEC( timeStepMSec );
|
||||
|
||||
moveResult = MM_OK;
|
||||
blockingEntity = NULL;
|
||||
oldOrigin = current.origin;
|
||||
|
||||
// if bound to a master
|
||||
if ( masterEntity ) {
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.origin = masterOrigin + current.localOrigin * masterAxis;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, clipModel->GetAxis() );
|
||||
// RAVEN END
|
||||
current.velocity = ( current.origin - oldOrigin ) / timeStep;
|
||||
masterDeltaYaw = masterYaw;
|
||||
masterYaw = masterAxis[0].ToYaw();
|
||||
masterDeltaYaw = masterYaw - masterDeltaYaw;
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the monster is at rest
|
||||
if ( current.atRest >= 0 ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ActivateContactEntities();
|
||||
|
||||
// move the monster velocity into the frame of a pusher
|
||||
current.velocity -= current.pushVelocity;
|
||||
|
||||
clipModel->Unlink();
|
||||
|
||||
// check if on the ground
|
||||
idPhysics_Monster::CheckGround( current );
|
||||
|
||||
// if not on the ground or moving upwards
|
||||
float upspeed;
|
||||
if ( gravityNormal != vec3_zero ) {
|
||||
upspeed = -( current.velocity * gravityNormal );
|
||||
} else {
|
||||
upspeed = current.velocity.z;
|
||||
}
|
||||
if ( fly || ( !forceDeltaMove && ( !current.onGround || upspeed > 1.0f ) ) ) {
|
||||
if ( upspeed < 0.0f ) {
|
||||
moveResult = MM_FALLING;
|
||||
}
|
||||
else {
|
||||
current.onGround = false;
|
||||
moveResult = MM_OK;
|
||||
}
|
||||
delta = current.velocity * timeStep;
|
||||
if ( delta != vec3_origin ) {
|
||||
moveResult = idPhysics_Monster::SlideMove( current.origin, current.velocity, delta );
|
||||
delta.Zero();
|
||||
}
|
||||
|
||||
if ( !fly ) {
|
||||
current.velocity += gravityVector * timeStep;
|
||||
}
|
||||
} else {
|
||||
if ( useVelocityMove ) {
|
||||
delta = current.velocity * timeStep;
|
||||
} else {
|
||||
current.velocity = delta / timeStep;
|
||||
}
|
||||
|
||||
current.velocity -= ( current.velocity * gravityNormal ) * gravityNormal;
|
||||
|
||||
if ( delta == vec3_origin ) {
|
||||
Rest();
|
||||
} else {
|
||||
// try moving into the desired direction
|
||||
// RAVEN BEGIN
|
||||
// jshepard: flying creatures, even if not using fly move, shouldn't use step move
|
||||
if( self->IsType( idAI::GetClassType() ) && ((idAI*)self)->move.moveType == MOVETYPE_FLY ) {
|
||||
moveResult = idPhysics_Monster::SlideMove( current.origin, current.velocity, delta );
|
||||
} else {
|
||||
moveResult = idPhysics_Monster::StepMove( current.origin, current.velocity, delta );
|
||||
}
|
||||
delta.Zero();
|
||||
// RAVEN END
|
||||
current.velocity -= ( current.velocity * gravityNormal ) * gravityNormal;
|
||||
}
|
||||
}
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, clipModel->GetAxis() );
|
||||
// RAVEN END
|
||||
|
||||
// get all the ground contacts
|
||||
EvaluateContacts();
|
||||
|
||||
// move the monster velocity back into the world frame
|
||||
current.velocity += current.pushVelocity;
|
||||
current.lastPushVelocity = current.pushVelocity;
|
||||
current.pushVelocity.Zero();
|
||||
|
||||
if ( IsOutsideWorld() ) {
|
||||
gameLocal.Warning( "clip model outside world bounds for entity '%s' at (%s)", self->name.c_str(), current.origin.ToString(0) );
|
||||
Rest();
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: determine if we moved this frame
|
||||
return true;
|
||||
// RAVEN END
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::UpdateTime
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::UpdateTime( int endTimeMSec ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::GetTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Monster::GetTime( void ) const {
|
||||
return gameLocal.time;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::GetImpactInfo
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
|
||||
info->invMass = invMass;
|
||||
info->invInertiaTensor.Zero();
|
||||
info->position.Zero();
|
||||
info->velocity = current.velocity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::ApplyImpulse
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
|
||||
if ( noImpact ) {
|
||||
return;
|
||||
}
|
||||
current.velocity += impulse * invMass;
|
||||
Activate();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::IsAtRest
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Monster::IsAtRest( void ) const {
|
||||
return current.atRest >= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::GetRestStartTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Monster::GetRestStartTime( void ) const {
|
||||
return current.atRest;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::SaveState
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::SaveState( void ) {
|
||||
saved = current;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::RestoreState
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::RestoreState( void ) {
|
||||
current = saved;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, clipModel->GetAxis() );
|
||||
// RAVEN END
|
||||
|
||||
EvaluateContacts();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Player::SetOrigin
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::SetOrigin( const idVec3 &newOrigin, int id ) {
|
||||
idVec3 masterOrigin;
|
||||
idMat3 masterAxis;
|
||||
|
||||
current.localOrigin = newOrigin;
|
||||
if ( masterEntity ) {
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.origin = masterOrigin + newOrigin * masterAxis;
|
||||
}
|
||||
else {
|
||||
current.origin = newOrigin;
|
||||
}
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, newOrigin, clipModel->GetAxis() );
|
||||
// RAVEN END
|
||||
Activate();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Player::SetAxis
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::SetAxis( const idMat3 &newAxis, int id ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, clipModel->GetOrigin(), newAxis );
|
||||
// RAVEN END
|
||||
Activate();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::Translate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::Translate( const idVec3 &translation, int id ) {
|
||||
|
||||
current.localOrigin += translation;
|
||||
current.origin += translation;
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, clipModel->GetAxis() );
|
||||
// RAVEN END
|
||||
Activate();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::Rotate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::Rotate( const idRotation &rotation, int id ) {
|
||||
idVec3 masterOrigin;
|
||||
idMat3 masterAxis;
|
||||
|
||||
current.origin *= rotation;
|
||||
if ( masterEntity ) {
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
|
||||
}
|
||||
else {
|
||||
current.localOrigin = current.origin;
|
||||
}
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, clipModel->GetAxis() * rotation.ToMat3() );
|
||||
// RAVEN END
|
||||
Activate();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::SetLinearVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
|
||||
current.velocity = newLinearVelocity;
|
||||
Activate();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::GetLinearVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Monster::GetLinearVelocity( int id ) const {
|
||||
return current.velocity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::SetPushed
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::SetPushed( int deltaTime ) {
|
||||
// velocity with which the monster is pushed
|
||||
current.pushVelocity += ( current.origin - saved.origin ) / ( deltaTime * idMath::M_MS2SEC );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::GetPushedLinearVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Monster::GetPushedLinearVelocity( const int id ) const {
|
||||
return current.lastPushVelocity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::SetMaster
|
||||
|
||||
the binding is never orientated
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::SetMaster( idEntity *master, const bool orientated ) {
|
||||
idVec3 masterOrigin;
|
||||
idMat3 masterAxis;
|
||||
|
||||
if ( master ) {
|
||||
if ( !masterEntity ) {
|
||||
// transform from world space to master space
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
|
||||
masterEntity = master;
|
||||
masterYaw = masterAxis[0].ToYaw();
|
||||
}
|
||||
ClearContacts();
|
||||
}
|
||||
else {
|
||||
if ( masterEntity ) {
|
||||
masterEntity = NULL;
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const float MONSTER_VELOCITY_MAX = 4000;
|
||||
const int MONSTER_VELOCITY_TOTAL_BITS = 16;
|
||||
const int MONSTER_VELOCITY_EXPONENT_BITS = idMath::BitsForInteger( idMath::BitsForFloat( MONSTER_VELOCITY_MAX ) ) + 1;
|
||||
const int MONSTER_VELOCITY_MANTISSA_BITS = MONSTER_VELOCITY_TOTAL_BITS - 1 - MONSTER_VELOCITY_EXPONENT_BITS;
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::WriteToSnapshot
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::WriteToSnapshot( idBitMsgDelta &msg ) const {
|
||||
msg.WriteFloat( current.origin[0] );
|
||||
msg.WriteFloat( current.origin[1] );
|
||||
msg.WriteFloat( current.origin[2] );
|
||||
msg.WriteFloat( current.velocity[0], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
msg.WriteFloat( current.velocity[1], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
msg.WriteFloat( current.velocity[2], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
msg.WriteDeltaFloat( current.origin[0], current.localOrigin[0] );
|
||||
msg.WriteDeltaFloat( current.origin[1], current.localOrigin[1] );
|
||||
msg.WriteDeltaFloat( current.origin[2], current.localOrigin[2] );
|
||||
msg.WriteDeltaFloat( 0.0f, current.pushVelocity[0], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
msg.WriteDeltaFloat( 0.0f, current.pushVelocity[1], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
msg.WriteDeltaFloat( 0.0f, current.pushVelocity[2], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
msg.WriteLong( current.atRest );
|
||||
msg.WriteBits( current.onGround, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Monster::ReadFromSnapshot
|
||||
================
|
||||
*/
|
||||
void idPhysics_Monster::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
||||
current.origin[0] = msg.ReadFloat();
|
||||
current.origin[1] = msg.ReadFloat();
|
||||
current.origin[2] = msg.ReadFloat();
|
||||
current.velocity[0] = msg.ReadFloat( MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
current.velocity[1] = msg.ReadFloat( MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
current.velocity[2] = msg.ReadFloat( MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
current.localOrigin[0] = msg.ReadDeltaFloat( current.origin[0] );
|
||||
current.localOrigin[1] = msg.ReadDeltaFloat( current.origin[1] );
|
||||
current.localOrigin[2] = msg.ReadDeltaFloat( current.origin[2] );
|
||||
current.pushVelocity[0] = msg.ReadDeltaFloat( 0.0f, MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
current.pushVelocity[1] = msg.ReadDeltaFloat( 0.0f, MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
current.pushVelocity[2] = msg.ReadDeltaFloat( 0.0f, MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
|
||||
current.atRest = msg.ReadLong();
|
||||
current.onGround = msg.ReadBits( 1 ) != 0;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
|
||||
#ifndef __PHYSICS_MONSTER_H__
|
||||
#define __PHYSICS_MONSTER_H__
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
Monster physics
|
||||
|
||||
Simulates the motion of a monster through the environment. The monster motion
|
||||
is typically driven by animations.
|
||||
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
MM_OK,
|
||||
MM_SLIDING,
|
||||
MM_BLOCKED,
|
||||
MM_STEPPED,
|
||||
MM_FALLING
|
||||
} monsterMoveResult_t;
|
||||
|
||||
typedef struct monsterPState_s {
|
||||
int atRest;
|
||||
bool onGround;
|
||||
idVec3 origin;
|
||||
idVec3 velocity;
|
||||
idVec3 localOrigin;
|
||||
idVec3 pushVelocity;
|
||||
// RAVEN BEGIN
|
||||
// bdube: added
|
||||
idVec3 lastPushVelocity;
|
||||
// RAVEN END
|
||||
} monsterPState_t;
|
||||
|
||||
class idPhysics_Monster : public idPhysics_Actor {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_Monster );
|
||||
|
||||
idPhysics_Monster( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
// maximum step up the monster can take, default 18 units
|
||||
void SetMaxStepHeight( const float newMaxStepHeight );
|
||||
float GetMaxStepHeight( void ) const;
|
||||
// minimum cosine of floor angle to be able to stand on the floor
|
||||
void SetMinFloorCosine( const float newMinFloorCosine );
|
||||
// set delta for next move
|
||||
void SetDelta( const idVec3 &d );
|
||||
// returns true if monster is standing on the ground
|
||||
bool OnGround( void ) const;
|
||||
// returns the movement result
|
||||
monsterMoveResult_t GetMoveResult( void ) const;
|
||||
// overrides any velocity for pure delta movement
|
||||
void ForceDeltaMove( bool force );
|
||||
// whether velocity should be affected by gravity
|
||||
void UseFlyMove( bool force );
|
||||
// don't use delta movement
|
||||
void UseVelocityMove( bool force );
|
||||
// get entity blocking the move
|
||||
idEntity * GetSlideMoveEntity( void ) const;
|
||||
// enable/disable activation by impact
|
||||
void EnableImpact( void );
|
||||
void DisableImpact( void );
|
||||
|
||||
public: // common physics interface
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const;
|
||||
void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
|
||||
void Activate( void );
|
||||
void PutToRest( void );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
|
||||
void SetPushed( int deltaTime );
|
||||
const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated = true );
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
private:
|
||||
// monster physics state
|
||||
monsterPState_t current;
|
||||
monsterPState_t saved;
|
||||
|
||||
// properties
|
||||
float maxStepHeight; // maximum step height
|
||||
float minFloorCosine; // minimum cosine of floor angle
|
||||
idVec3 delta; // delta for next move
|
||||
|
||||
bool forceDeltaMove;
|
||||
bool fly;
|
||||
bool useVelocityMove;
|
||||
bool noImpact; // if true do not activate when another object collides
|
||||
|
||||
// results of last evaluate
|
||||
monsterMoveResult_t moveResult;
|
||||
idEntity * blockingEntity;
|
||||
|
||||
private:
|
||||
void CheckGround( monsterPState_t &state );
|
||||
monsterMoveResult_t SlideMove( idVec3 &start, idVec3 &velocity, const idVec3 &delta );
|
||||
monsterMoveResult_t StepMove( idVec3 &start, idVec3 &velocity, const idVec3 &delta );
|
||||
void Rest( void );
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_MONSTER_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,163 @@
|
||||
|
||||
#ifndef __PHYSICS_PARAMETRIC_H__
|
||||
#define __PHYSICS_PARAMETRIC_H__
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
Parametric physics
|
||||
|
||||
Used for predefined or scripted motion. The motion of an object is completely
|
||||
parametrized. By adjusting the parameters an object is forced to follow a
|
||||
predefined path. The parametric physics is typically used for doors, bridges,
|
||||
rotating fans etc.
|
||||
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
typedef struct parametricPState_s {
|
||||
int time; // physics time
|
||||
int atRest; // set when simulation is suspended
|
||||
idVec3 origin; // world origin
|
||||
idAngles angles; // world angles
|
||||
idMat3 axis; // world axis
|
||||
idVec3 localOrigin; // local origin
|
||||
idAngles localAngles; // local angles
|
||||
idExtrapolate<idVec3> linearExtrapolation; // extrapolation based description of the position over time
|
||||
idExtrapolate<idAngles> angularExtrapolation; // extrapolation based description of the orientation over time
|
||||
idInterpolateAccelDecelLinear<idVec3> linearInterpolation; // interpolation based description of the position over time
|
||||
idInterpolateAccelDecelLinear<idAngles> angularInterpolation; // interpolation based description of the orientation over time
|
||||
idCurve_Spline<idVec3> * spline; // spline based description of the position over time
|
||||
idInterpolateAccelDecelLinear<float> splineInterpolate; // position along the spline over time
|
||||
bool useSplineAngles; // set the orientation using the spline
|
||||
} parametricPState_t;
|
||||
|
||||
class idPhysics_Parametric : public idPhysics_Base {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_Parametric );
|
||||
|
||||
idPhysics_Parametric( void );
|
||||
~idPhysics_Parametric( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
void SetPusher( int flags );
|
||||
bool IsPusher( void ) const;
|
||||
|
||||
void SetLinearExtrapolation( extrapolation_t type, int time, int duration, const idVec3 &base, const idVec3 &speed, const idVec3 &baseSpeed );
|
||||
void SetAngularExtrapolation( extrapolation_t type, int time, int duration, const idAngles &base, const idAngles &speed, const idAngles &baseSpeed );
|
||||
extrapolation_t GetLinearExtrapolationType( void ) const;
|
||||
extrapolation_t GetAngularExtrapolationType( void ) const;
|
||||
|
||||
void SetLinearInterpolation( int time, int accelTime, int decelTime, int duration, const idVec3 &startPos, const idVec3 &endPos );
|
||||
void SetAngularInterpolation( int time, int accelTime, int decelTime, int duration, const idAngles &startAng, const idAngles &endAng );
|
||||
|
||||
void SetSpline( idCurve_Spline<idVec3> *spline, int accelTime, int decelTime, bool useSplineAngles );
|
||||
idCurve_Spline<idVec3> *GetSpline( void ) const;
|
||||
int GetSplineAcceleration( void ) const;
|
||||
int GetSplineDeceleration( void ) const;
|
||||
bool UsingSplineAngles( void ) const;
|
||||
|
||||
void GetLocalOrigin( idVec3 &curOrigin ) const;
|
||||
void GetLocalAngles( idAngles &curAngles ) const;
|
||||
|
||||
void GetAngles( idAngles &curAngles ) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// abahr: a method for hiding gimblelock
|
||||
void SetAxisOffset( const idMat3& offset ) { axisOffset = offset; useAxisOffset = true; }
|
||||
const idMat3& GetAxisOffset() const { return axisOffset; }
|
||||
idMat3& GetAxisOffset() { return axisOffset; }
|
||||
bool UseAxisOffset() const { return useAxisOffset; }
|
||||
// RAVEN END
|
||||
|
||||
public: // common physics interface
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
int GetNumClipModels( void ) const;
|
||||
|
||||
void SetMass( float mass, int id = -1 );
|
||||
float GetMass( int id = -1 ) const;
|
||||
|
||||
void SetContents( int contents, int id = -1 );
|
||||
int GetContents( int id = -1 ) const;
|
||||
|
||||
const idBounds & GetBounds( int id = -1 ) const;
|
||||
const idBounds & GetAbsBounds( int id = -1 ) const;
|
||||
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
void Activate( void );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
bool IsPushable( void ) const;
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
const idVec3 & GetOrigin( int id = 0 ) const;
|
||||
const idMat3 & GetAxis( int id = 0 ) const;
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
void SetAngularVelocity( const idVec3 &newAngularVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
const idVec3 & GetAngularVelocity( int id = 0 ) const;
|
||||
|
||||
void DisableClip( void );
|
||||
void EnableClip( void );
|
||||
|
||||
void UnlinkClip( void );
|
||||
void LinkClip( void );
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated = true );
|
||||
|
||||
const trace_t * GetBlockingInfo( void ) const;
|
||||
idEntity * GetBlockingEntity( void ) const;
|
||||
|
||||
int GetLinearEndTime( void ) const;
|
||||
int GetAngularEndTime( void ) const;
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
private:
|
||||
// parametric physics state
|
||||
parametricPState_t current;
|
||||
parametricPState_t saved;
|
||||
|
||||
// pusher
|
||||
bool isPusher;
|
||||
idClipModel * clipModel;
|
||||
int pushFlags;
|
||||
|
||||
// results of last evaluate
|
||||
trace_t pushResults;
|
||||
bool isBlocked;
|
||||
|
||||
// master
|
||||
bool hasMaster;
|
||||
bool isOrientated;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// abahr: a method for hiding gimblelock
|
||||
bool useAxisOffset;
|
||||
idMat3 axisOffset;
|
||||
// RAVEN END
|
||||
|
||||
private:
|
||||
bool TestIfAtRest( void ) const;
|
||||
void Rest( void );
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_PARAMETRIC_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
||||
#ifndef __PHYSICS_PARTICLE_H__
|
||||
#define __PHYSICS_PARTICLE_H__
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
Particle Physics
|
||||
|
||||
Employs an impulse based dynamic simulation which is not very accurate but
|
||||
relatively fast and still reliable due to the continuous collision detection.
|
||||
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
typedef struct particlePState_s {
|
||||
int atRest; // set when simulation is suspended
|
||||
idVec3 localOrigin; // origin relative to master
|
||||
idMat3 localAxis; // axis relative to master
|
||||
idVec3 pushVelocity; // push velocity
|
||||
idVec3 origin;
|
||||
idVec3 velocity;
|
||||
bool onGround;
|
||||
bool inWater;
|
||||
} particlePState_t;
|
||||
|
||||
class rvPhysics_Particle : public idPhysics_Base {
|
||||
|
||||
public:
|
||||
|
||||
CLASS_PROTOTYPE( rvPhysics_Particle );
|
||||
|
||||
rvPhysics_Particle( void );
|
||||
~rvPhysics_Particle( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
// initialisation
|
||||
void SetFriction( const float linear, const float angular, const float contact );
|
||||
void SetBouncyness( const float b, bool allowBounce );
|
||||
|
||||
// put to rest untill something collides with this physics object
|
||||
void PutToRest( void );
|
||||
// same as above but drop to the floor first
|
||||
void DropToFloor( void );
|
||||
|
||||
// returns true if touching the ground
|
||||
bool IsOnGround ( void ) const;
|
||||
bool IsInWater ( void ) const;
|
||||
|
||||
public: // common physics interface
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
int GetNumClipModels( void ) const;
|
||||
|
||||
void SetContents( int contents, int id = -1 );
|
||||
int GetContents( int id = -1 ) const;
|
||||
|
||||
const idBounds & GetBounds( int id = -1 ) const;
|
||||
const idBounds & GetAbsBounds( int id = -1 ) const;
|
||||
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
bool CanBounce ( void ) const;
|
||||
|
||||
bool EvaluateContacts( void );
|
||||
|
||||
void Activate( void );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
bool IsPushable( void ) const;
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
const idVec3 & GetOrigin( int id = 0 ) const;
|
||||
const idMat3 & GetAxis( int id = 0 ) const;
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
|
||||
void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
|
||||
void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
|
||||
int ClipContents( const idClipModel *model ) const;
|
||||
|
||||
void DisableClip( void );
|
||||
void EnableClip( void );
|
||||
|
||||
void UnlinkClip( void );
|
||||
void LinkClip( void );
|
||||
|
||||
void SetPushed( int deltaTime );
|
||||
const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated );
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
idEntityPtr<idEntity> extraPassEntity;
|
||||
|
||||
private:
|
||||
// state of the particle
|
||||
particlePState_t current;
|
||||
particlePState_t saved;
|
||||
|
||||
// particle properties
|
||||
float linearFriction; // translational friction
|
||||
float angularFriction; // rotational friction
|
||||
float contactFriction; // friction with contact surfaces
|
||||
float bouncyness; // bouncyness
|
||||
bool allowBounce; // Allowed to bounce at all?
|
||||
idClipModel * clipModel; // clip model used for collision detection
|
||||
|
||||
bool dropToFloor; // true if dropping to the floor and putting to rest
|
||||
bool testSolid; // true if testing for inside solid during a drop
|
||||
|
||||
// master
|
||||
bool hasMaster;
|
||||
bool isOrientated;
|
||||
|
||||
private:
|
||||
|
||||
void DropToFloorAndRest ( void );
|
||||
bool SlideMove ( idVec3& start, idVec3& velocity, const idVec3& delta );
|
||||
void CheckGround ( void );
|
||||
void ApplyFriction ( float timeStep );
|
||||
void DebugDraw ( void );
|
||||
};
|
||||
|
||||
ID_INLINE bool rvPhysics_Particle::IsOnGround ( void ) const {
|
||||
return current.onGround;
|
||||
}
|
||||
|
||||
ID_INLINE bool rvPhysics_Particle::IsInWater ( void ) const {
|
||||
return current.inWater;
|
||||
}
|
||||
|
||||
ID_INLINE bool rvPhysics_Particle::CanBounce ( void ) const {
|
||||
return allowBounce;
|
||||
}
|
||||
|
||||
#endif /* !__PHYSICS_PARTICLE_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,198 @@
|
||||
|
||||
#ifndef __PHYSICS_PLAYER_H__
|
||||
#define __PHYSICS_PLAYER_H__
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
Player physics
|
||||
|
||||
Simulates the motion of a player through the environment. Input from the
|
||||
player is used to allow a certain degree of control over the motion.
|
||||
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
// movementType
|
||||
typedef enum {
|
||||
PM_NORMAL, // normal physics
|
||||
PM_DEAD, // no acceleration or turning, but free falling
|
||||
PM_SPECTATOR, // flying without gravity but with collision detection
|
||||
PM_FREEZE, // stuck in place without control
|
||||
PM_NOCLIP // flying without collision detection nor gravity
|
||||
} pmtype_t;
|
||||
|
||||
typedef enum {
|
||||
WATERLEVEL_NONE,
|
||||
WATERLEVEL_FEET,
|
||||
WATERLEVEL_WAIST,
|
||||
WATERLEVEL_HEAD
|
||||
} waterLevel_t;
|
||||
|
||||
#define MAXTOUCH 32
|
||||
|
||||
typedef struct playerPState_s {
|
||||
idVec3 origin;
|
||||
idVec3 velocity;
|
||||
idVec3 localOrigin;
|
||||
idVec3 pushVelocity;
|
||||
// RAVEN BEGIN
|
||||
// bdube: added
|
||||
idVec3 lastPushVelocity;
|
||||
// RAVEN END
|
||||
float stepUp;
|
||||
int movementType;
|
||||
int movementFlags;
|
||||
int movementTime;
|
||||
// RAVEN BEGIN
|
||||
// bdube: crouch slide
|
||||
int crouchSlideTime;
|
||||
// RAVEN END
|
||||
} playerPState_t;
|
||||
|
||||
class idPhysics_Player : public idPhysics_Actor {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_Player );
|
||||
|
||||
idPhysics_Player( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
// initialisation
|
||||
void SetSpeed( const float newWalkSpeed, const float newCrouchSpeed );
|
||||
void SetMaxStepHeight( const float newMaxStepHeight );
|
||||
float GetMaxStepHeight( void ) const;
|
||||
void SetMaxJumpHeight( const float newMaxJumpHeight );
|
||||
void SetMovementType( const pmtype_t type );
|
||||
void SetPlayerInput( const usercmd_t &cmd, const idAngles &newViewAngles );
|
||||
void SetKnockBack( const int knockBackTime );
|
||||
void SetDebugLevel( bool set );
|
||||
// feed back from last physics frame
|
||||
waterLevel_t GetWaterLevel( void ) const;
|
||||
int GetWaterType( void ) const;
|
||||
bool HasJumped( void ) const;
|
||||
bool HasSteppedUp( void ) const;
|
||||
float GetStepUp( void ) const;
|
||||
bool IsCrouching( void ) const;
|
||||
bool OnLadder( void ) const;
|
||||
const idVec3 & PlayerGetOrigin( void ) const; // != GetOrigin
|
||||
|
||||
public: // common physics interface
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const;
|
||||
void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
|
||||
void SetPushed( int deltaTime );
|
||||
const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
|
||||
void ClearPushedVelocity( void );
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated = true );
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
// RAVEN BEGIN
|
||||
// kfuller: Added
|
||||
bool IsNoclip( void ) const;
|
||||
bool IsDead( void ) const;
|
||||
// RAVEN END
|
||||
|
||||
void SetClipModelNoLink( idClipModel *clip );
|
||||
|
||||
private:
|
||||
// player physics state
|
||||
playerPState_t current;
|
||||
playerPState_t saved;
|
||||
|
||||
// properties
|
||||
float walkSpeed;
|
||||
float crouchSpeed;
|
||||
float maxStepHeight;
|
||||
float maxJumpHeight;
|
||||
int debugLevel; // if set, diagnostic output will be printed
|
||||
|
||||
// player input
|
||||
usercmd_t command;
|
||||
idAngles viewAngles;
|
||||
|
||||
// run-time variables
|
||||
int framemsec;
|
||||
float frametime;
|
||||
float playerSpeed;
|
||||
idVec3 viewForward;
|
||||
idVec3 viewRight;
|
||||
|
||||
// walk movement
|
||||
bool walking;
|
||||
bool groundPlane;
|
||||
trace_t groundTrace;
|
||||
const idMaterial * groundMaterial;
|
||||
|
||||
// ladder movement
|
||||
bool ladder;
|
||||
idVec3 ladderNormal;
|
||||
|
||||
// results of last evaluate
|
||||
waterLevel_t waterLevel;
|
||||
int waterType;
|
||||
|
||||
private:
|
||||
float CmdScale( const usercmd_t &cmd ) const;
|
||||
void Accelerate( const idVec3 &wishdir, const float wishspeed, const float accel );
|
||||
bool SlideMove( bool gravity, bool stepUp, bool stepDown, bool push );
|
||||
void Friction( void );
|
||||
void WaterJumpMove( void );
|
||||
void WaterMove( void );
|
||||
void FlyMove( void );
|
||||
void AirMove( void );
|
||||
void WalkMove( void );
|
||||
void DeadMove( void );
|
||||
void NoclipMove( void );
|
||||
void SpectatorMove( void );
|
||||
void LadderMove( void );
|
||||
void CorrectAllSolid( trace_t &trace, int contents );
|
||||
// RAVEN BEGIN
|
||||
// MrE: check stuck
|
||||
void CheckGround( bool checkStuck );
|
||||
// RAVEN END
|
||||
void CheckDuck( void );
|
||||
void CheckLadder( void );
|
||||
bool CheckJump( void );
|
||||
bool CheckWaterJump( void );
|
||||
void SetWaterLevel( void );
|
||||
void DropTimers( void );
|
||||
void MovePlayer( int msec );
|
||||
|
||||
float Pm_Accelerate( void );
|
||||
float Pm_AirAccelerate( void );
|
||||
};
|
||||
|
||||
ID_INLINE bool idPhysics_Player::IsNoclip( void ) const {
|
||||
return current.movementType == PM_NOCLIP;
|
||||
}
|
||||
|
||||
ID_INLINE bool idPhysics_Player::IsDead( void ) const {
|
||||
return current.movementType == PM_DEAD;
|
||||
}
|
||||
|
||||
#endif /* !__PHYSICS_PLAYER_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,172 @@
|
||||
|
||||
#ifndef __PHYSICS_RIGIDBODY_H__
|
||||
#define __PHYSICS_RIGIDBODY_H__
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
Rigid body physics
|
||||
|
||||
Employs an impulse based dynamic simulation which is not very accurate but
|
||||
relatively fast and still reliable due to the continuous collision detection.
|
||||
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
typedef struct rididBodyIState_s {
|
||||
idVec3 position; // position of trace model
|
||||
idMat3 orientation; // orientation of trace model
|
||||
idVec3 linearMomentum; // translational momentum relative to center of mass
|
||||
idVec3 angularMomentum; // rotational momentum relative to center of mass
|
||||
} rigidBodyIState_t;
|
||||
|
||||
typedef struct rigidBodyPState_s {
|
||||
int atRest; // set when simulation is suspended
|
||||
float lastTimeStep; // length of last time step
|
||||
idVec3 localOrigin; // origin relative to master
|
||||
idMat3 localAxis; // axis relative to master
|
||||
idVec6 pushVelocity; // push velocity
|
||||
idVec3 externalForce; // external force relative to center of mass
|
||||
idVec3 externalTorque; // external torque relative to center of mass
|
||||
rigidBodyIState_t i; // state used for integration
|
||||
} rigidBodyPState_t;
|
||||
|
||||
class idPhysics_RigidBody : public idPhysics_Base {
|
||||
|
||||
public:
|
||||
|
||||
CLASS_PROTOTYPE( idPhysics_RigidBody );
|
||||
|
||||
idPhysics_RigidBody( void );
|
||||
~idPhysics_RigidBody( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
// initialisation
|
||||
void SetFriction( const float linear, const float angular, const float contact );
|
||||
void SetBouncyness( const float b );
|
||||
// same as above but drop to the floor first
|
||||
void DropToFloor( void );
|
||||
// no contact determination and contact friction
|
||||
void NoContact( void );
|
||||
// enable/disable activation by impact
|
||||
void EnableImpact( void );
|
||||
void DisableImpact( void );
|
||||
|
||||
public: // common physics interface
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
int GetNumClipModels( void ) const;
|
||||
|
||||
void SetMass( float mass, int id = -1 );
|
||||
float GetMass( int id = -1 ) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: means of getting center of mass
|
||||
idVec3 GetCenterMass ( int id = -1 ) const;
|
||||
// RAVEN END
|
||||
|
||||
void SetContents( int contents, int id = -1 );
|
||||
int GetContents( int id = -1 ) const;
|
||||
|
||||
const idBounds & GetBounds( int id = -1 ) const;
|
||||
const idBounds & GetAbsBounds( int id = -1 ) const;
|
||||
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const;
|
||||
void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
|
||||
void AddForce( const int id, const idVec3 &point, const idVec3 &force );
|
||||
void Activate( void );
|
||||
void PutToRest( void );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
bool IsPushable( void ) const;
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
const idVec3 & GetOrigin( int id = 0 ) const;
|
||||
const idMat3 & GetAxis( int id = 0 ) const;
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
void SetAngularVelocity( const idVec3 &newAngularVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
const idVec3 & GetAngularVelocity( int id = 0 ) const;
|
||||
|
||||
void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
|
||||
void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
|
||||
int ClipContents( const idClipModel *model ) const;
|
||||
|
||||
void DisableClip( void );
|
||||
void EnableClip( void );
|
||||
|
||||
void UnlinkClip( void );
|
||||
void LinkClip( void );
|
||||
|
||||
bool EvaluateContacts( void );
|
||||
|
||||
void SetPushed( int deltaTime );
|
||||
const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
|
||||
const idVec3 & GetPushedAngularVelocity( const int id = 0 ) const;
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated );
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
protected:
|
||||
|
||||
// state of the rigid body
|
||||
rigidBodyPState_t current;
|
||||
rigidBodyPState_t saved;
|
||||
|
||||
private:
|
||||
|
||||
// rigid body properties
|
||||
float linearFriction; // translational friction
|
||||
float angularFriction; // rotational friction
|
||||
float contactFriction; // friction with contact surfaces
|
||||
float bouncyness; // bouncyness
|
||||
idClipModel * clipModel; // clip model used for collision detection
|
||||
|
||||
// derived properties
|
||||
float mass; // mass of body
|
||||
float inverseMass; // 1 / mass
|
||||
idVec3 centerOfMass; // center of mass of trace model
|
||||
idMat3 inertiaTensor; // mass distribution
|
||||
idMat3 inverseInertiaTensor; // inverse inertia tensor
|
||||
|
||||
idODE * integrator; // integrator
|
||||
bool dropToFloor; // true if dropping to the floor and putting to rest
|
||||
bool testSolid; // true if testing for solid when dropping to the floor
|
||||
bool noImpact; // if true do not activate when another object collides
|
||||
bool noContact; // if true do not determine contacts and no contact friction
|
||||
|
||||
// master
|
||||
bool hasMaster;
|
||||
bool isOrientated;
|
||||
|
||||
private:
|
||||
friend void RigidBodyDerivatives( const float t, const void *clientData, const float *state, float *derivatives );
|
||||
void Integrate( const float deltaTime, rigidBodyPState_t &next );
|
||||
bool CheckForCollisions( const float deltaTime, rigidBodyPState_t &next, trace_t &collision );
|
||||
bool CollisionImpulse( const trace_t &collision, idVec3 &impulse );
|
||||
void ContactFriction( float deltaTime );
|
||||
void DropToFloorAndRest( void );
|
||||
bool TestIfAtRest( void ) const;
|
||||
void Rest( void );
|
||||
void DebugDraw( void );
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_RIGIDBODY_H__ */
|
||||
@@ -0,0 +1,882 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idPhysics, idPhysics_Static )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::idPhysics_Static
|
||||
================
|
||||
*/
|
||||
idPhysics_Static::idPhysics_Static( void ) {
|
||||
self = NULL;
|
||||
clipModel = NULL;
|
||||
current.origin.Zero();
|
||||
current.axis.Identity();
|
||||
current.localOrigin.Zero();
|
||||
current.localAxis.Identity();
|
||||
hasMaster = false;
|
||||
isOrientated = false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::~idPhysics_Static
|
||||
================
|
||||
*/
|
||||
idPhysics_Static::~idPhysics_Static( void ) {
|
||||
if ( self && self->GetPhysics() == this ) {
|
||||
self->SetPhysics( NULL );
|
||||
}
|
||||
idForce::DeletePhysics( this );
|
||||
if ( clipModel ) {
|
||||
delete clipModel;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::Save
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::Save( idSaveGame *savefile ) const {
|
||||
savefile->WriteObject( self );
|
||||
|
||||
savefile->WriteVec3( current.origin );
|
||||
savefile->WriteMat3( current.axis );
|
||||
savefile->WriteVec3( current.localOrigin );
|
||||
savefile->WriteMat3( current.localAxis );
|
||||
savefile->WriteClipModel( clipModel );
|
||||
|
||||
savefile->WriteBool( hasMaster );
|
||||
savefile->WriteBool( isOrientated );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::Restore
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::Restore( idRestoreGame *savefile ) {
|
||||
savefile->ReadObject( reinterpret_cast<idClass *&>( self ) );
|
||||
|
||||
savefile->ReadVec3( current.origin );
|
||||
savefile->ReadMat3( current.axis );
|
||||
savefile->ReadVec3( current.localOrigin );
|
||||
savefile->ReadMat3( current.localAxis );
|
||||
savefile->ReadClipModel( clipModel );
|
||||
|
||||
savefile->ReadBool( hasMaster );
|
||||
savefile->ReadBool( isOrientated );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetSelf
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetSelf( idEntity *e ) {
|
||||
assert( e );
|
||||
self = e;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetClipModel
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetClipModel( idClipModel *model, float density, int id, bool freeOld ) {
|
||||
assert( self );
|
||||
|
||||
if ( clipModel && clipModel != model && freeOld ) {
|
||||
delete clipModel;
|
||||
}
|
||||
clipModel = model;
|
||||
if ( clipModel ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, current.axis );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetClipModel
|
||||
================
|
||||
*/
|
||||
idClipModel *idPhysics_Static::GetClipModel( int id ) const {
|
||||
if ( clipModel ) {
|
||||
return clipModel;
|
||||
}
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
return idClip::DefaultClipModel();
|
||||
// RAVEN END
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetNumClipModels
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::GetNumClipModels( void ) const {
|
||||
return ( clipModel != NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetMass
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetMass( float mass, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetMass
|
||||
================
|
||||
*/
|
||||
float idPhysics_Static::GetMass( int id ) const {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: Added center mass call
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetCenterMass
|
||||
|
||||
default center of mass is origin
|
||||
================
|
||||
*/
|
||||
idVec3 idPhysics_Static::GetCenterMass ( int id ) const {
|
||||
return GetOrigin();
|
||||
}
|
||||
// RAVEN END
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetContents
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetContents( int contents, int id ) {
|
||||
if ( clipModel ) {
|
||||
clipModel->SetContents( contents );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetContents
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::GetContents( int id ) const {
|
||||
if ( clipModel ) {
|
||||
return clipModel->GetContents();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetClipMask
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetClipMask( int mask, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetClipMask
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::GetClipMask( int id ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetBounds
|
||||
================
|
||||
*/
|
||||
const idBounds &idPhysics_Static::GetBounds( int id ) const {
|
||||
if ( clipModel ) {
|
||||
return clipModel->GetBounds();
|
||||
}
|
||||
return bounds_zero;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetAbsBounds
|
||||
================
|
||||
*/
|
||||
const idBounds &idPhysics_Static::GetAbsBounds( int id ) const {
|
||||
static idBounds absBounds;
|
||||
|
||||
if ( clipModel ) {
|
||||
return clipModel->GetAbsBounds();
|
||||
}
|
||||
absBounds[0] = absBounds[1] = current.origin;
|
||||
return absBounds;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::Evaluate
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Static::Evaluate( int timeStepMSec, int endTimeMSec ) {
|
||||
// RAVEN BEGIN
|
||||
// bdube: draw bbox
|
||||
if ( hasMaster ) {
|
||||
idVec3 masterOrigin;
|
||||
idVec3 oldOrigin;
|
||||
idMat3 masterAxis;
|
||||
idMat3 oldAxis;
|
||||
// RAVEN END
|
||||
|
||||
oldOrigin = current.origin;
|
||||
oldAxis = current.axis;
|
||||
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.origin = masterOrigin + current.localOrigin * masterAxis;
|
||||
if ( isOrientated ) {
|
||||
current.axis = current.localAxis * masterAxis;
|
||||
} else {
|
||||
current.axis = current.localAxis;
|
||||
}
|
||||
if ( clipModel ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, current.axis );
|
||||
// RAVEN END
|
||||
}
|
||||
|
||||
return ( current.origin != oldOrigin || current.axis != oldAxis );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::UpdateTime
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::UpdateTime( int endTimeMSec ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::GetTime( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetImpactInfo
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
|
||||
memset( info, 0, sizeof( *info ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::ApplyImpulse
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::AddForce
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::AddForce( const int id, const idVec3 &point, const idVec3 &force ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::Activate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::Activate( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::PutToRest
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::PutToRest( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::IsAtRest
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Static::IsAtRest( void ) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetRestStartTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::GetRestStartTime( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::IsPushable
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Static::IsPushable( void ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: water interraction
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::IsInWater
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Static::IsInWater ( void ) const {
|
||||
return false;
|
||||
}
|
||||
// RAVEN END
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SaveState
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SaveState( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::RestoreState
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::RestoreState( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetOrigin
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetOrigin( const idVec3 &newOrigin, int id ) {
|
||||
idVec3 masterOrigin;
|
||||
idMat3 masterAxis;
|
||||
|
||||
current.localOrigin = newOrigin;
|
||||
|
||||
if ( hasMaster ) {
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.origin = masterOrigin + newOrigin * masterAxis;
|
||||
} else {
|
||||
current.origin = newOrigin;
|
||||
}
|
||||
|
||||
if ( clipModel ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, current.axis );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetAxis
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetAxis( const idMat3 &newAxis, int id ) {
|
||||
idVec3 masterOrigin;
|
||||
idMat3 masterAxis;
|
||||
|
||||
current.localAxis = newAxis;
|
||||
|
||||
if ( hasMaster && isOrientated ) {
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.axis = newAxis * masterAxis;
|
||||
} else {
|
||||
current.axis = newAxis;
|
||||
}
|
||||
|
||||
if ( clipModel ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, current.axis );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::Translate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::Translate( const idVec3 &translation, int id ) {
|
||||
current.localOrigin += translation;
|
||||
current.origin += translation;
|
||||
|
||||
if ( clipModel ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, current.axis );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::Rotate
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::Rotate( const idRotation &rotation, int id ) {
|
||||
idVec3 masterOrigin;
|
||||
idMat3 masterAxis;
|
||||
|
||||
current.origin *= rotation;
|
||||
current.axis *= rotation.ToMat3();
|
||||
|
||||
if ( hasMaster ) {
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.localAxis *= rotation.ToMat3();
|
||||
current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
|
||||
} else {
|
||||
current.localAxis = current.axis;
|
||||
current.localOrigin = current.origin;
|
||||
}
|
||||
|
||||
if ( clipModel ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, current.axis );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetOrigin
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Static::GetOrigin( int id ) const {
|
||||
return current.origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetAxis
|
||||
================
|
||||
*/
|
||||
const idMat3 &idPhysics_Static::GetAxis( int id ) const {
|
||||
return current.axis;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetLinearVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetAngularVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetLinearVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Static::GetLinearVelocity( int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetAngularVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Static::GetAngularVelocity( int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetGravity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetGravity( const idVec3 &newGravity ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetGravity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Static::GetGravity( void ) const {
|
||||
static idVec3 gravity( 0, 0, -g_gravity.GetFloat() );
|
||||
if( gameLocal.isMultiplayer ) {
|
||||
gravity = idVec3( 0, 0, -g_mp_gravity.GetFloat() );
|
||||
}
|
||||
|
||||
return gravity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetGravityNormal
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Static::GetGravityNormal( void ) const {
|
||||
static idVec3 gravity( 0, 0, -1 );
|
||||
return gravity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::ClipTranslation
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
|
||||
if ( model ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.TranslationModel( self, results, current.origin, current.origin + translation,
|
||||
clipModel, current.axis, MASK_SOLID, model->GetCollisionModel(), model->GetOrigin(), model->GetAxis() );
|
||||
} else {
|
||||
gameLocal.Translation( self, results, current.origin, current.origin + translation,
|
||||
clipModel, current.axis, MASK_SOLID, self );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::ClipRotation
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
|
||||
if ( model ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
gameLocal.RotationModel( self, results, current.origin, rotation,
|
||||
clipModel, current.axis, MASK_SOLID, model->GetCollisionModel(), model->GetOrigin(), model->GetAxis() );
|
||||
} else {
|
||||
gameLocal.Rotation( self, results, current.origin, rotation, clipModel, current.axis, MASK_SOLID, self );
|
||||
}
|
||||
// RAVEN END
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::ClipContents
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::ClipContents( const idClipModel *model ) const {
|
||||
if ( clipModel ) {
|
||||
if ( model ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple collision worlds
|
||||
return gameLocal.ContentsModel( self, clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1,
|
||||
model->GetCollisionModel(), model->GetOrigin(), model->GetAxis() );
|
||||
} else {
|
||||
return gameLocal.Contents( self, clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1, NULL );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::DisableClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::DisableClip( void ) {
|
||||
if ( clipModel ) {
|
||||
clipModel->Disable();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::EnableClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::EnableClip( void ) {
|
||||
if ( clipModel ) {
|
||||
clipModel->Enable();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::UnlinkClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::UnlinkClip( void ) {
|
||||
if ( clipModel ) {
|
||||
clipModel->Unlink();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::LinkClip
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::LinkClip( void ) {
|
||||
if ( clipModel ) {
|
||||
// RAVEN BEGIN
|
||||
// ddynerman: multiple clip worlds
|
||||
clipModel->Link( self, 0, current.origin, current.axis );
|
||||
// RAVEN END
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::EvaluateContacts
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Static::EvaluateContacts( void ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetNumContacts
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::GetNumContacts( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetContact
|
||||
================
|
||||
*/
|
||||
const contactInfo_t &idPhysics_Static::GetContact( int num ) const {
|
||||
static contactInfo_t info;
|
||||
memset( &info, 0, sizeof( info ) );
|
||||
return info;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::ClearContacts
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::ClearContacts( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::AddContactEntity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::AddContactEntity( idEntity *e ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::RemoveContactEntity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::RemoveContactEntity( idEntity *e ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::HasGroundContacts
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Static::HasGroundContacts( void ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::IsGroundEntity
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Static::IsGroundEntity( int entityNum ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::IsGroundClipModel
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Static::IsGroundClipModel( int entityNum, int id ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetPushed
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetPushed( int deltaTime ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetPushedLinearVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Static::GetPushedLinearVelocity( const int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetPushedAngularVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Static::GetPushedAngularVelocity( const int id ) const {
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::SetMaster
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::SetMaster( idEntity *master, const bool orientated ) {
|
||||
idVec3 masterOrigin;
|
||||
idMat3 masterAxis;
|
||||
|
||||
if ( master ) {
|
||||
if ( !hasMaster ) {
|
||||
// transform from world space to master space
|
||||
self->GetMasterPosition( masterOrigin, masterAxis );
|
||||
current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
|
||||
if ( orientated ) {
|
||||
current.localAxis = current.axis * masterAxis.Transpose();
|
||||
} else {
|
||||
current.localAxis = current.axis;
|
||||
}
|
||||
hasMaster = true;
|
||||
isOrientated = orientated;
|
||||
}
|
||||
} else {
|
||||
if ( hasMaster ) {
|
||||
hasMaster = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetBlockingInfo
|
||||
================
|
||||
*/
|
||||
const trace_t *idPhysics_Static::GetBlockingInfo( void ) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetBlockingEntity
|
||||
================
|
||||
*/
|
||||
idEntity *idPhysics_Static::GetBlockingEntity( void ) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetLinearEndTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::GetLinearEndTime( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::GetAngularEndTime
|
||||
================
|
||||
*/
|
||||
int idPhysics_Static::GetAngularEndTime( void ) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Static::WriteToSnapshot
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::WriteToSnapshot( idBitMsgDelta &msg ) const {
|
||||
idCQuat quat, localQuat;
|
||||
|
||||
quat = current.axis.ToCQuat();
|
||||
localQuat = current.localAxis.ToCQuat();
|
||||
|
||||
msg.WriteFloat( current.origin[0] );
|
||||
msg.WriteFloat( current.origin[1] );
|
||||
msg.WriteFloat( current.origin[2] );
|
||||
msg.WriteFloat( quat.x );
|
||||
msg.WriteFloat( quat.y );
|
||||
msg.WriteFloat( quat.z );
|
||||
msg.WriteDeltaFloat( current.origin[0], current.localOrigin[0] );
|
||||
msg.WriteDeltaFloat( current.origin[1], current.localOrigin[1] );
|
||||
msg.WriteDeltaFloat( current.origin[2], current.localOrigin[2] );
|
||||
msg.WriteDeltaFloat( quat.x, localQuat.x );
|
||||
msg.WriteDeltaFloat( quat.y, localQuat.y );
|
||||
msg.WriteDeltaFloat( quat.z, localQuat.z );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::ReadFromSnapshot
|
||||
================
|
||||
*/
|
||||
void idPhysics_Static::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
||||
idCQuat quat, localQuat;
|
||||
|
||||
current.origin[0] = msg.ReadFloat();
|
||||
current.origin[1] = msg.ReadFloat();
|
||||
current.origin[2] = msg.ReadFloat();
|
||||
quat.x = msg.ReadFloat();
|
||||
quat.y = msg.ReadFloat();
|
||||
quat.z = msg.ReadFloat();
|
||||
current.localOrigin[0] = msg.ReadDeltaFloat( current.origin[0] );
|
||||
current.localOrigin[1] = msg.ReadDeltaFloat( current.origin[1] );
|
||||
current.localOrigin[2] = msg.ReadDeltaFloat( current.origin[2] );
|
||||
localQuat.x = msg.ReadDeltaFloat( quat.x );
|
||||
localQuat.y = msg.ReadDeltaFloat( quat.y );
|
||||
localQuat.z = msg.ReadDeltaFloat( quat.z );
|
||||
|
||||
current.axis = quat.ToMat3();
|
||||
current.localAxis = localQuat.ToMat3();
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
|
||||
#ifndef __PHYSICS_STATIC_H__
|
||||
#define __PHYSICS_STATIC_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Physics for a non moving object using at most one collision model.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
// RAVEN BEGIN
|
||||
// rjohnson: converted this from a struct to a class
|
||||
class idStaticPState {
|
||||
|
||||
public:
|
||||
idVec3 origin;
|
||||
idMat3 axis;
|
||||
idVec3 localOrigin;
|
||||
idMat3 localAxis;
|
||||
|
||||
idStaticPState( void ) { }
|
||||
};
|
||||
// RAVEN END
|
||||
|
||||
class idPhysics_Static : public idPhysics {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_Static );
|
||||
|
||||
idPhysics_Static( void );
|
||||
~idPhysics_Static( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
public: // common physics interface
|
||||
void SetSelf( idEntity *e );
|
||||
//RAVEN BEGIN
|
||||
// abahr: for gravity
|
||||
virtual idEntity* GetSelf() const { return self; }
|
||||
// RAVEN END
|
||||
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
int GetNumClipModels( void ) const;
|
||||
|
||||
void SetMass( float mass, int id = -1 );
|
||||
float GetMass( int id = -1 ) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: means of getting center of mass
|
||||
idVec3 GetCenterMass( int id = -1 ) const;
|
||||
// RAVEN END
|
||||
|
||||
void SetContents( int contents, int id = -1 );
|
||||
int GetContents( int id = -1 ) const;
|
||||
|
||||
void SetClipMask( int mask, int id = -1 );
|
||||
int GetClipMask( int id = -1 ) const;
|
||||
|
||||
const idBounds & GetBounds( int id = -1 ) const;
|
||||
const idBounds & GetAbsBounds( int id = -1 ) const;
|
||||
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const;
|
||||
void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
|
||||
void AddForce( const int id, const idVec3 &point, const idVec3 &force );
|
||||
void Activate( void );
|
||||
void PutToRest( void );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
bool IsPushable( void ) const;
|
||||
// RAVEN BEGIN
|
||||
// bdube: water interraction
|
||||
bool IsInWater ( void ) const;
|
||||
// RAVEN END
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
const idVec3 & GetOrigin( int id = 0 ) const;
|
||||
const idMat3 & GetAxis( int id = 0 ) const;
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
void SetAngularVelocity( const idVec3 &newAngularVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
const idVec3 & GetAngularVelocity( int id = 0 ) const;
|
||||
|
||||
void SetGravity( const idVec3 &newGravity );
|
||||
const idVec3 & GetGravity( void ) const;
|
||||
const idVec3 & GetGravityNormal( void ) const;
|
||||
|
||||
void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
|
||||
void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
|
||||
int ClipContents( const idClipModel *model ) const;
|
||||
|
||||
void DisableClip( void );
|
||||
void EnableClip( void );
|
||||
|
||||
void UnlinkClip( void );
|
||||
void LinkClip( void );
|
||||
|
||||
bool EvaluateContacts( void );
|
||||
int GetNumContacts( void ) const;
|
||||
const contactInfo_t & GetContact( int num ) const;
|
||||
void ClearContacts( void );
|
||||
void AddContactEntity( idEntity *e );
|
||||
void RemoveContactEntity( idEntity *e );
|
||||
|
||||
bool HasGroundContacts( void ) const;
|
||||
bool IsGroundEntity( int entityNum ) const;
|
||||
bool IsGroundClipModel( int entityNum, int id ) const;
|
||||
|
||||
void SetPushed( int deltaTime );
|
||||
const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
|
||||
const idVec3 & GetPushedAngularVelocity( const int id = 0 ) const;
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated = true );
|
||||
|
||||
const trace_t * GetBlockingInfo( void ) const;
|
||||
idEntity * GetBlockingEntity( void ) const;
|
||||
|
||||
int GetLinearEndTime( void ) const;
|
||||
int GetAngularEndTime( void ) const;
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
protected:
|
||||
|
||||
idEntity * self; // entity using this physics object
|
||||
// RAVEN BEGIN
|
||||
// rjohnson: converted this from a struct to a class
|
||||
idStaticPState current; // physics state
|
||||
// RAVEN END
|
||||
idClipModel * clipModel; // collision model
|
||||
|
||||
// master
|
||||
bool hasMaster;
|
||||
bool isOrientated;
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_STATIC_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
|
||||
#ifndef __PHYSICS_STATICMULTI_H__
|
||||
#define __PHYSICS_STATICMULTI_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Physics for a non moving object using no or multiple collision models.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idPhysics_StaticMulti : public idPhysics {
|
||||
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_StaticMulti );
|
||||
|
||||
idPhysics_StaticMulti( void );
|
||||
~idPhysics_StaticMulti( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
void RemoveIndex( int id = 0, bool freeClipModel = true );
|
||||
|
||||
public: // common physics interface
|
||||
|
||||
void SetSelf( idEntity *e );
|
||||
//RAVEN BEGIN
|
||||
// abahr: for gravity
|
||||
virtual idEntity* GetSelf() const { return self; }
|
||||
// RAVEN END
|
||||
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
int GetNumClipModels( void ) const;
|
||||
|
||||
void SetMass( float mass, int id = -1 );
|
||||
float GetMass( int id = -1 ) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// bdube: means of getting center of mass
|
||||
idVec3 GetCenterMass( int id = -1 ) const;
|
||||
// RAVEN END
|
||||
|
||||
void SetContents( int contents, int id = -1 );
|
||||
int GetContents( int id = -1 ) const;
|
||||
|
||||
void SetClipMask( int mask, int id = -1 );
|
||||
int GetClipMask( int id = -1 ) const;
|
||||
|
||||
const idBounds & GetBounds( int id = -1 ) const;
|
||||
const idBounds & GetAbsBounds( int id = -1 ) const;
|
||||
|
||||
bool Evaluate( int timeStepMSec, int endTimeMSec );
|
||||
void UpdateTime( int endTimeMSec );
|
||||
int GetTime( void ) const;
|
||||
|
||||
void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const;
|
||||
void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
|
||||
void AddForce( const int id, const idVec3 &point, const idVec3 &force );
|
||||
void Activate( void );
|
||||
void PutToRest( void );
|
||||
bool IsAtRest( void ) const;
|
||||
int GetRestStartTime( void ) const;
|
||||
bool IsPushable( void ) const;
|
||||
// RAVEN BEGIN
|
||||
// bdube: water interraction
|
||||
bool IsInWater ( void ) const;
|
||||
// RAVEN END
|
||||
|
||||
void SaveState( void );
|
||||
void RestoreState( void );
|
||||
|
||||
void SetOrigin( const idVec3 &newOrigin, int id = -1 );
|
||||
void SetAxis( const idMat3 &newAxis, int id = -1 );
|
||||
|
||||
void Translate( const idVec3 &translation, int id = -1 );
|
||||
void Rotate( const idRotation &rotation, int id = -1 );
|
||||
|
||||
const idVec3 & GetOrigin( int id = 0 ) const;
|
||||
const idMat3 & GetAxis( int id = 0 ) const;
|
||||
|
||||
void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
|
||||
void SetAngularVelocity( const idVec3 &newAngularVelocity, int id = 0 );
|
||||
|
||||
const idVec3 & GetLinearVelocity( int id = 0 ) const;
|
||||
const idVec3 & GetAngularVelocity( int id = 0 ) const;
|
||||
|
||||
void SetGravity( const idVec3 &newGravity );
|
||||
const idVec3 & GetGravity( void ) const;
|
||||
const idVec3 & GetGravityNormal( void ) const;
|
||||
|
||||
void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
|
||||
void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
|
||||
int ClipContents( const idClipModel *model ) const;
|
||||
|
||||
void DisableClip( void );
|
||||
void EnableClip( void );
|
||||
|
||||
void UnlinkClip( void );
|
||||
void LinkClip( void );
|
||||
|
||||
bool EvaluateContacts( void );
|
||||
int GetNumContacts( void ) const;
|
||||
const contactInfo_t & GetContact( int num ) const;
|
||||
void ClearContacts( void );
|
||||
void AddContactEntity( idEntity *e );
|
||||
void RemoveContactEntity( idEntity *e );
|
||||
|
||||
bool HasGroundContacts( void ) const;
|
||||
bool IsGroundEntity( int entityNum ) const;
|
||||
bool IsGroundClipModel( int entityNum, int id ) const;
|
||||
|
||||
void SetPushed( int deltaTime );
|
||||
const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
|
||||
const idVec3 & GetPushedAngularVelocity( const int id = 0 ) const;
|
||||
|
||||
void SetMaster( idEntity *master, const bool orientated = true );
|
||||
|
||||
const trace_t * GetBlockingInfo( void ) const;
|
||||
idEntity * GetBlockingEntity( void ) const;
|
||||
|
||||
int GetLinearEndTime( void ) const;
|
||||
int GetAngularEndTime( void ) const;
|
||||
|
||||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
protected:
|
||||
idEntity * self; // entity using this physics object
|
||||
// RAVEN BEGIN
|
||||
// rjohnson: converted this from a struct to a class
|
||||
idList<idStaticPState> current; // physics state
|
||||
// RAVEN END
|
||||
idList<idClipModel *> clipModels; // collision model
|
||||
|
||||
// master
|
||||
bool hasMaster;
|
||||
bool isOrientated;
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_STATICMULTI_H__ */
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( idPhysics_RigidBody, rvPhysics_VehicleMonster )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
rvPhysics_VehicleMonster::Evaluate
|
||||
|
||||
Evaluate the impulse based rigid body physics.
|
||||
When a collision occurs an impulse is applied at the moment of impact but
|
||||
the remaining time after the collision is ignored.
|
||||
================
|
||||
*/
|
||||
bool rvPhysics_VehicleMonster::Evaluate( int timeStepMSec, int endTimeMSec ) {
|
||||
if ( idPhysics_RigidBody::Evaluate( timeStepMSec, endTimeMSec ) ) {
|
||||
|
||||
idAngles euler = current.i.orientation.ToAngles();
|
||||
euler.pitch = 0.0f;
|
||||
euler.roll = 0.0f;
|
||||
current.i.orientation = euler.ToMat3();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void rvPhysics_VehicleMonster::SetGravity ( const idVec3 & v ) {
|
||||
gravityVector = v;
|
||||
gravityNormal = gameLocal.GetGravity( );
|
||||
gravityNormal.Normalize();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
#ifndef __PHYSICS_VEHICLE_MONSTER_H__
|
||||
#define __PHYSICS_VEHICLE_MONSTER_H__
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
Vehicle Monster Physics
|
||||
|
||||
Employs an impulse based dynamic simulation which is not very accurate but
|
||||
relatively fast and still reliable due to the continuous collision detection.
|
||||
Extents particle physics with the ability to apply impulses.
|
||||
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
class rvPhysics_VehicleMonster : public idPhysics_RigidBody {
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvPhysics_VehicleMonster );
|
||||
|
||||
bool Evaluate ( int timeStepMSec, int endTimeMSec );
|
||||
void SetGravity ( const idVec3 & v );
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_VEHICLE_MONSTER_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
|
||||
#ifndef __PUSH_H__
|
||||
#define __PUSH_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Allows physics objects to be pushed geometrically.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#define PUSHFL_ONLYMOVEABLE 1 // only push moveable entities
|
||||
#define PUSHFL_NOGROUNDENTITIES 2 // don't push entities the clip model rests upon
|
||||
#define PUSHFL_CLIP 4 // also clip against all non-moveable entities
|
||||
#define PUSHFL_CRUSH 8 // kill blocking entities
|
||||
#define PUSHFL_APPLYIMPULSE 16 // apply impulse to pushed entities
|
||||
|
||||
//#define NEW_PUSH
|
||||
|
||||
class idPush {
|
||||
public:
|
||||
// Try to push other entities by moving the given entity.
|
||||
// If results.fraction < 1.0 the move was blocked by results.c.entityNum
|
||||
// Returns total mass of all pushed entities.
|
||||
float ClipTranslationalPush( trace_t &results, idEntity *pusher, const int flags,
|
||||
const idVec3 &newOrigin, const idVec3 &move );
|
||||
|
||||
float ClipRotationalPush( trace_t &results, idEntity *pusher, const int flags,
|
||||
const idMat3 &newAxis, const idRotation &rotation );
|
||||
|
||||
float ClipPush( trace_t &results, idEntity *pusher, const int flags,
|
||||
const idVec3 &oldOrigin, const idMat3 &oldAxis,
|
||||
idVec3 &newOrigin, idMat3 &newAxis );
|
||||
|
||||
// initialize saving the positions of entities being pushed
|
||||
void InitSavingPushedEntityPositions( void );
|
||||
// move all pushed entities back to their previous position
|
||||
void RestorePushedEntityPositions( void );
|
||||
// returns the number of pushed entities
|
||||
int GetNumPushedEntities( void ) const { return numPushed; }
|
||||
// get the ith pushed entity
|
||||
idEntity * GetPushedEntity( int i ) const { assert( i >= 0 && i < numPushed ); return pushed[i].ent; }
|
||||
|
||||
private:
|
||||
struct pushed_s {
|
||||
idEntity * ent; // pushed entity
|
||||
idAngles deltaViewAngles; // actor delta view angles
|
||||
} pushed[MAX_GENTITIES]; // pushed entities
|
||||
int numPushed; // number of pushed entities
|
||||
|
||||
struct pushedGroup_s {
|
||||
idEntity * ent;
|
||||
float fraction;
|
||||
bool groundContact;
|
||||
bool test;
|
||||
} pushedGroup[MAX_GENTITIES];
|
||||
int pushedGroupSize;
|
||||
|
||||
private:
|
||||
void SaveEntityPosition( idEntity *ent );
|
||||
bool RotateEntityToAxial( idEntity *ent, idVec3 rotationPoint );
|
||||
#ifdef NEW_PUSH
|
||||
bool CanPushEntity( idEntity *ent, idEntity *pusher, idEntity *initialPusher, const int flags );
|
||||
void AddEntityToPushedGroup( idEntity *ent, float fraction, bool groundContact );
|
||||
bool IsFullyPushed( idEntity *ent );
|
||||
bool ClipTranslationAgainstPusher( trace_t &results, idEntity *ent, idEntity *pusher, const idVec3 &translation );
|
||||
int GetPushableEntitiesForTranslation( idEntity *pusher, idEntity *initialPusher, const int flags,
|
||||
const idVec3 &translation, idEntity *entityList[], int maxEntities );
|
||||
bool ClipRotationAgainstPusher( trace_t &results, idEntity *ent, idEntity *pusher, const idRotation &rotation );
|
||||
int GetPushableEntitiesForRotation( idEntity *pusher, idEntity *initialPusher, const int flags,
|
||||
const idRotation &rotation, idEntity *entityList[], int maxEntities );
|
||||
#else
|
||||
void ClipEntityRotation( trace_t &trace, const idEntity *ent, const idClipModel *clipModel,
|
||||
idClipModel *skip, const idRotation &rotation );
|
||||
void ClipEntityTranslation( trace_t &trace, const idEntity *ent, const idClipModel *clipModel,
|
||||
idClipModel *skip, const idVec3 &translation );
|
||||
int TryTranslatePushEntity( trace_t &results, idEntity *check, idClipModel *clipModel, const int flags,
|
||||
const idVec3 &newOrigin, const idVec3 &move );
|
||||
int TryRotatePushEntity( trace_t &results, idEntity *check, idClipModel *clipModel, const int flags,
|
||||
const idMat3 &newAxis, const idRotation &rotation );
|
||||
int DiscardEntities( idEntity *entityList[], int numEntities, int flags, idEntity *pusher );
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* !__PUSH_H__ */
|
||||
Reference in New Issue
Block a user