Initial Prey Game integration support.

This commit is contained in:
Justin Marshall
2026-05-05 15:01:01 -07:00
parent a6c6f1ed26
commit 8d5f678b25
552 changed files with 265551 additions and 209 deletions
File diff suppressed because it is too large Load Diff
+397
View File
@@ -0,0 +1,397 @@
// Copyright (C) 2004 Id Software, Inc.
//
#ifndef __CLIP_H__
#define __CLIP_H__
#if _HH_CLIP_FASTSECTORS //HUMANHEAD rww
const int CLIPSECTOR_DEPTH = 6;
const int CLIPSECTOR_WIDTH = 1 << CLIPSECTOR_DEPTH;
#endif //HUMANHEAD 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 );
explicit idClipModel( const int renderModelHandle );
explicit idClipModel( const idClipModel *model );
~idClipModel( void );
#if _HH_CLIP_FASTSECTORS //HUMANHEAD rww
void UpdateDynamicContents( void );
#endif //HUMANHEAD END
bool LoadModel( const char *name );
void LoadModel( const idTraceModel &trm );
void LoadModel( const int renderModelHandle );
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Link( idClip &clp ); // must have been linked with an entity and id before
void Link( idClip &clp, idEntity *ent, int newId, const idVec3 &newOrigin, const idMat3 &newAxis, int renderModelHandle = -1 );
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 SetMaterial( const idMaterial *m );
const idMaterial * GetMaterial( void ) const;
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;
cmHandle_t Handle( void ) const; // returns handle used to collide vs this model
const idTraceModel * GetTraceModel( void ) const;
void GetMassProperties( const float density, float &mass, idVec3 &centerOfMass, idMat3 &inertiaTensor ) const;
static cmHandle_t CheckModel( const char *name );
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
#if _HH_CLIP_FASTSECTORS //HUMANHEAD rww
bool checked; // Splash's clip model code
#endif //HUMANHEAD 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
const idMaterial * material; // material for trace models
int contents; // all contents ored together
cmHandle_t collisionModelHandle; // 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
#if !_HH_CLIP_FASTSECTORS //HUMANHEAD rww
void Link_r( struct clipSector_s *node );
#endif //HUMANHEAD END
static int AllocTraceModel( const idTraceModel &trm );
static void FreeTraceModel( int traceModelIndex );
static idTraceModel * GetCachedTraceModel( 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::SetMaterial( const idMaterial *m ) {
material = m;
}
ID_INLINE const idMaterial * idClipModel::GetMaterial( void ) const {
return material;
}
ID_INLINE void idClipModel::SetContents( int newContents ) {
contents = newContents;
#if _HH_CLIP_FASTSECTORS //HUMANHEAD rww
UpdateDynamicContents();
#endif //HUMANHEAD 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
bool Translation( trace_t &results, const idVec3 &start, const idVec3 &end,
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity );
//HUMANEHAD rww - translation with overhead of checking game logic for collision allowance
bool TranslationWithExceptions( trace_t &results, const idVec3 &start, const idVec3 &end, idEntity *ent,
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity );
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 );
int Contents( const idVec3 &start,
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity );
// 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,
cmHandle_t 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,
cmHandle_t 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,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
int ContentsModel( const idVec3 &start,
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
// clip versus all entities but not the world
void TranslationEntities( trace_t &results, const idVec3 &start, const idVec3 &end,
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity );
// 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;
const idBounds & GetWorldBounds( void ) const;
idClipModel * DefaultClipModel( void );
// stats and debug drawing
void PrintStatistics( void );
void DrawClipModels( const idVec3 &eye, const float radius, const idEntity *passEntity );
bool DrawModelContactFeature( const contactInfo_t &contact, const idClipModel *clipModel, int lifetime ) const;
#if _HH_CLIP_FASTSECTORS //HUMANHEAD rww
void CoordsForBounds( int* coords, idBounds& bounds ) const;
static void UpdateDynamicContents( struct clipSector_s* sector );
static void UpdateDynamicContents( idClipModel* clipModel );
#endif //HUMANHEAD END
// HUMANHEAD pdm
void DrawClipModelsInTree_r( const struct clipSector_s *node, const idVec3 &eye );
// HUMANHEAD END
#if !GOLD //HUMANHEAD rww
bool CheckClipEntMatch( const struct clipSector_s *node, const idClipModel *currentClip, const idEntity *ent ) const;
#endif //HUMANHEAD END
private:
#if _HH_CLIP_FASTSECTORS //HUMANHEAD rww
idVec3 nodeScale;
idVec3 nodeOffset;
idVec3 nodeOffsetVisual;
#endif //HUMANHEAD END
int numClipSectors;
struct clipSector_s * clipSectors;
idBounds worldBounds;
idClipModel temporaryClipModel;
idClipModel defaultClipModel;
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 );
#if !_HH_CLIP_FASTSECTORS //HUMANHEAD rww
void ClipModelsTouchingBounds_r( const struct clipSector_s *node, struct listParms_s &parms ) const;
#endif //HUMANHEAD END
const idTraceModel * TraceModelForClipModel( const idClipModel *mdl ) const;
int GetTraceClipModels( const idBounds &bounds, int contentMask, const idEntity *passEntity, idClipModel **clipModelList ) const;
void TraceRenderModel( trace_t &trace, const idVec3 &start, const idVec3 &end, const float radius, const idMat3 &axis, idClipModel *touch ) const;
#if _HH_CLIP_FASTSECTORS //HUMANHEAD rww
void GetClipSectorsStaticContents( void );
#endif //HUMANHEAD 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 ) );
Translation( results, start, end, &temporaryClipModel, mat3_identity, contentMask, passEntity );
return ( results.fraction < 1.0f );
}
ID_INLINE const idBounds & idClip::GetWorldBounds( void ) const {
return worldBounds;
}
ID_INLINE idClipModel *idClip::DefaultClipModel( void ) {
return &defaultClipModel;
}
#if _HH_CLIP_FASTSECTORS //HUMANHEAD rww
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 ]++;
}
#endif //HUMANHEAD END
#endif /* !__CLIP_H__ */
+68
View File
@@ -0,0 +1,68 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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 ) {
}
+41
View File
@@ -0,0 +1,41 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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__ */
+110
View File
@@ -0,0 +1,110 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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 );
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;
}
}
+46
View File
@@ -0,0 +1,46 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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__ */
+130
View File
@@ -0,0 +1,130 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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( USERCMD_MSEC ), id );
velocity = physics->GetLinearVelocity( id ) * damping + dir1 * ( ( l1 - l2 ) * ( 1.0f - damping ) / MS2SEC( USERCMD_MSEC ) );
physics->SetLinearVelocity( velocity, id );
}
/*
================
idForce_Drag::RemovePhysics
================
*/
void idForce_Drag::RemovePhysics( const idPhysics *phys ) {
if ( physics == phys ) {
physics = NULL;
}
}
+49
View File
@@ -0,0 +1,49 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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__ */
+243
View File
@@ -0,0 +1,243 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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;
}
/*
================
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 );
}
/*
================
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 );
}
/*
================
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 ];
//HUMANHEAD: aob
idVec3 linearVelocity;
assert( clipModel );
bounds.FromTransformedBounds( clipModel->GetBounds(), clipModel->GetOrigin(), clipModel->GetAxis() );
numClipModels = gameLocal.clip.ClipModelsTouchingBounds( bounds, -1, clipModelList, MAX_GENTITIES );
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 ) {
if ( !physics->IsType( idPhysics_Player::Type ) ) {
continue;
}
} else if ( monsterOnly ) {
if ( !physics->IsType( idPhysics_Monster::Type ) ) {
continue;
}
}
//HUMANHEAD: aob - should ignore players that noclip
if ( !monsterOnly ) {
idEntity* entity = cm->GetEntity();
if ( entity->IsType( idPlayer::Type ) && static_cast<idPlayer *>(entity)->noclip ) {
continue;
}
}
//HUMANHEAD END
if ( !gameLocal.clip.ContentsModel( cm->GetOrigin(), cm, cm->GetAxis(), -1,
clipModel->Handle(), clipModel->GetOrigin(), clipModel->GetAxis() ) ) {
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;
}
}
}
}
+69
View File
@@ -0,0 +1,69 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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 );
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;
};
#endif /* !__FORCE_FIELD_H__ */
+183
View File
@@ -0,0 +1,183 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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( idEntity *physics1, int id1, const idVec3 &p1, idEntity *physics2, int id2, const idVec3 &p2 ) { // HUMANHEAD mdl: Changed physics1 and physics2 to idEntity instead of the entity's physics object
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.IsValid() ) { // HUMANHEAD mdl: Added IsValid()
axis = physics1->GetPhysics()->GetAxis( id1 ); // HUMANHEAD: Added GetPhysics()
pos1 = physics1->GetPhysics()->GetOrigin( id1 ); // HUMANHEAD: Added GetPhysics()
pos1 += p1 * axis;
if ( damping > 0.0f ) {
physics1->GetPhysics()->GetImpactInfo( id1, pos1, &info ); // HUMANHEAD: Added GetPhysics()
velocity1 = info.velocity;
}
}
if ( physics2.IsValid() ) { // HUMANHEAD mdl: Added IsValid()
axis = physics2->GetPhysics()->GetAxis( id2 ); // HUMANHEAD: Added GetPhysics()
pos2 = physics2->GetPhysics()->GetOrigin( id2 ); // HUMANHEAD: Added GetPhysics()
pos2 += p2 * axis;
if ( damping > 0.0f ) {
physics2->GetPhysics()->GetImpactInfo( id2, pos2, &info ); // HUMANHEAD: Added GetPhysics()
velocity2 = info.velocity;
}
}
force = pos2 - pos1;
#ifdef _HH_FLOAT_PROTECTION //HUMANHEAD rww
if (FLOAT_IS_NAN(velocity1.x) || FLOAT_IS_NAN(velocity1.y) || FLOAT_IS_NAN(velocity1.z) ||
FLOAT_IS_NAN(velocity2.x) || FLOAT_IS_NAN(velocity2.y) || FLOAT_IS_NAN(velocity2.z)) {
gameLocal.DWarning( "idForce_Spring::Evaluate: NaN velocity." );
return;
}
#endif //HUMANHEAD END
if (force == vec3_origin) { //HUMANHEAD rww
//gameLocal.Warning( "idForce_Spring::Evaluate: force equal to zero." );
dampingForce = vec3_origin;
}
else { //HUMANHEAD END
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.IsValid() ) { // HUMANHEAD mdl: Added IsValid()
physics1->GetPhysics()->AddForce( id1, pos1, force ); // HUMANHEAD: Added GetPhysics()
}
if ( physics2.IsValid() ) { // HUMANHEAD mdl: Added IsValid()
physics2->GetPhysics()->AddForce( id2, pos2, -force ); // HUMANHEAD: Added GetPhysics()
}
}
}
else {
if ( Kcompress > 0.0f ) {
force = ( Square( length - restLength ) * Kcompress ) * force - dampingForce;
if ( physics1.IsValid() ) { // HUMANHEAD mdl: Added IsValid()
physics1->GetPhysics()->AddForce( id1, pos1, -force ); // HUMANHEAD: Added GetPhysics()
}
if ( physics2.IsValid() ) { // HUMANHEAD mdl: Added IsValid()
physics2->GetPhysics()->AddForce( id2, pos2, force ); // HUMANHEAD: Added GetPhysics()
}
}
}
}
/*
================
idForce_Spring::RemovePhysics
================
*/
void idForce_Spring::RemovePhysics( const idEntity *phys ) { // HUMANHEAD mdl: Changed to take entity instead of its physics object
if ( physics1.GetEntity() == phys ) { // HUMANHEAD mdl: Added GetEntity()
physics1 = NULL;
}
if ( physics2.GetEntity() == phys ) { // HUMANHEAD mdl: Added GetEntity()
physics2 = NULL;
}
}
// HUMANHEAD mdl
void idForce_Spring::Save( idSaveGame *savefile ) const {
savefile->WriteFloat( Kstretch );
savefile->WriteFloat( Kcompress );
savefile->WriteFloat( damping );
savefile->WriteFloat( restLength );
physics1.Save( savefile );
savefile->WriteInt( id1 );
savefile->WriteVec3( p1 );
physics2.Save( savefile );
savefile->WriteInt( id2 );
savefile->WriteVec3( p2 );
}
void idForce_Spring::Restore( idRestoreGame *savefile ) {
savefile->ReadFloat( Kstretch );
savefile->ReadFloat( Kcompress );
savefile->ReadFloat( damping );
savefile->ReadFloat( restLength );
physics1.Restore( savefile );
savefile->ReadInt( id1 );
savefile->ReadVec3( p1 );
physics2.Restore( savefile );
savefile->ReadInt( id2 );
savefile->ReadVec3( p2 );
}
// HUMANHEAD END
+55
View File
@@ -0,0 +1,55 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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( idEntity *physics1, int id1, const idVec3 &p1,
idEntity *physics2, int id2, const idVec3 &p2 ); // HUMANHEAD mdl: Changed to taking entities instead of their physics objects
// HUMANHEAD mdl: Added Save/Restore
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
// HUMANHEAD END
public: // common force interface
virtual void Evaluate( int time );
virtual void RemovePhysics( const idEntity *phys ); // HUMANHEAD mdl: Changed to take entity instead of its physics object
private:
// spring properties
float Kstretch;
float Kcompress;
float damping;
float restLength;
// positioning
idEntityPtr< idEntity > physics1; // first physics object // HUMANHEAD mdl: Changed to entity
int id1; // clip model id of first physics object
idVec3 p1; // position on clip model
idEntityPtr< idEntity > physics2; // second physics object // HUMANHEAD mdl: Changed to entity
int id2; // clip model id of second physics object
idVec3 p2; // position on clip model
};
#endif /* !__FORCE_SPRING_H__ */
+55
View File
@@ -0,0 +1,55 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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;
s = t + USERCMD_MSEC - 1;
return ( s - s % USERCMD_MSEC );
}
+162
View File
@@ -0,0 +1,162 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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;
// 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;
// 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;
// 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;
//HUMANHEAD: aob - need declarations so we can call these with GetPhysics()
virtual void ActivateContactEntities( void ) {}
//HUMANHEAD END
};
#endif /* !__PHYSICS_H__ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+671
View File
@@ -0,0 +1,671 @@
// Copyright (C) 2004 Id Software, Inc.
//
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
CLASS_DECLARATION( idPhysics_Base, idPhysics_Actor )
END_CLASS
//HUMANHEAD PCF mdl 04/30/06 - Added this in case last minute change below causes chaos
#define LAST_MINUTE_HACK
/*
================
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;
// HUMANHEAD nla
numTouch = 0;
memset( &groundTrace, 0, sizeof(trace_t) );
hadGroundContacts = false;
// HUMANHEAD END
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 );
// HUMANHEAD mdl
int i;
savefile->WriteTrace( groundTrace );
savefile->WriteInt( numTouch );
for( i = 0; i < MAXTOUCH; i++ ) {
savefile->WriteInt( touchEnts[i] );
}
savefile->WriteBool( hadGroundContacts );
for( i = 0; i < c_iNumRotationTraces; i++ ) {
savefile->WriteVec3( rotationTraceDirectionTable[i] );
}
// HUMANHEAD END
}
/*
================
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 );
// HUMANHEAD mdl
int i;
savefile->ReadTrace( groundTrace );
savefile->ReadInt( numTouch );
for( i = 0; i < MAXTOUCH; i++ ) {
savefile->ReadInt( touchEnts[i] );
}
savefile->ReadBool( hadGroundContacts );
for( i = 0; i < c_iNumRotationTraces; i++ ) {
savefile->ReadVec3( rotationTraceDirectionTable[i] );
}
// HUMANHEAD END
}
/*
================
idPhysics_Actor::SetClipModelAxis
================
*/
void idPhysics_Actor::SetClipModelAxis( void ) {
idMat3 prevClipModelAxis = clipModelAxis; // HUMANHEAD JRM
// align clip model to gravity direction
if ( ( gravityNormal[2] == -1.0f ) || ( gravityNormal == vec3_zero ) ) {
clipModelAxis.Identity();
}
else {
// HUMANHEAD JRM/PDM/NLA - To get the right clipmodel axis in gravity zones
idVec3 newx;
newx = prevClipModelAxis[0] - (prevClipModelAxis[0] * -gravityNormal)*-gravityNormal;
if(newx.LengthSqr() < VECTOR_EPSILON) {
gameLocal.Warning("idPhysics_Actor::SetClipModelAxis invalid newx");
if(prevClipModelAxis[0] * -gravityNormal > 0.0f) {
newx = -prevClipModelAxis[2];
}
else {
newx = prevClipModelAxis[2];
}
}
newx.Normalize();
clipModelAxis[0] = newx;
clipModelAxis[2] = -gravityNormal;
clipModelAxis[1] = clipModelAxis[2].Cross(clipModelAxis[0]);
// HUMANHEAD END
}
if ( clipModel ) {
clipModel->Link( gameLocal.clip, self, 0, clipModel->GetOrigin(), clipModelAxis );
}
}
/*
================
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;
clipModel->Link( gameLocal.clip, self, 0, clipModel->GetOrigin(), clipModelAxis );
}
/*
================
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::SetClipMask
================
*/
void idPhysics_Actor::SetContents( int contents, int id ) {
clipModel->SetContents( contents );
}
/*
================
idPhysics_Actor::SetClipMask
================
*/
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 );
/* HUMANHEAD: aob - removed because InterativeRotateMove updates bbox
SetClipModelAxis();
HUMANHEAD END*/
}
}
/*
================
idPhysics_Actor::ClipTranslation
================
*/
void idPhysics_Actor::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
if ( model ) {
gameLocal.clip.TranslationModel( results, clipModel->GetOrigin(), clipModel->GetOrigin() + translation,
clipModel, clipModel->GetAxis(), clipMask,
model->Handle(), model->GetOrigin(), model->GetAxis() );
}
else {
gameLocal.clip.Translation( results, clipModel->GetOrigin(), clipModel->GetOrigin() + translation,
clipModel, clipModel->GetAxis(), clipMask, self );
}
}
/*
================
idPhysics_Actor::ClipRotation
================
*/
void idPhysics_Actor::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
if ( model ) {
gameLocal.clip.RotationModel( results, clipModel->GetOrigin(), rotation,
clipModel, clipModel->GetAxis(), clipMask,
model->Handle(), model->GetOrigin(), model->GetAxis() );
}
else {
gameLocal.clip.Rotation( results, clipModel->GetOrigin(), rotation,
clipModel, clipModel->GetAxis(), clipMask, self );
}
}
/*
================
idPhysics_Actor::ClipContents
================
*/
int idPhysics_Actor::ClipContents( const idClipModel *model ) const {
if ( model ) {
return gameLocal.clip.ContentsModel( clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1,
model->Handle(), model->GetOrigin(), model->GetAxis() );
}
else {
return gameLocal.clip.Contents( clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1, NULL );
}
}
/*
================
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 ) {
clipModel->Link( gameLocal.clip, self, 0, clipModel->GetOrigin(), clipModel->GetAxis() );
}
/*
================
idPhysics_Actor::EvaluateContacts
================
*/
bool idPhysics_Actor::EvaluateContacts( void ) {
// get all the ground contacts
ClearContacts();
AddGroundContacts( clipModel );
AddContactEntitiesForContacts();
return ( contacts.Num() != 0 );
}
// HUMANHEAD functions
/*
===============
idPhysics_Actor::AddTouchEnt
HUMANHEAD nla
===============
*/
void idPhysics_Actor::AddTouchEnt( int entityNum ) {
int i;
if ( entityNum == ENTITYNUM_WORLD ) {
return;
}
if ( numTouch == MAXTOUCH ) {
return;
}
// see if it is already added
for ( i = 0; i < numTouch; i++ ) {
if ( touchEnts[ i ] == entityNum ) {
return;
}
}
// add it
touchEnts[numTouch] = entityNum;
numTouch++;
}
/*
===============
idPhysics_Actor::AddTouchEntList
HUMANHEAD nla
===============
*/
void idPhysics_Actor::AddTouchEntList( idList<int> &list ) {
int i;
for ( i = 0; i < list.Num(); i++ ) {
AddTouchEnt(list[i]);
}
}
/*
================
idPhysics_Actor::GetNumTouchEnts
HUMANHEAD nla
================
*/
int idPhysics_Actor::GetNumTouchEnts( void ) const {
return numTouch;
}
/*
================
idPhysics_Actor::GetTouchEnt
HUMANHEAD nla
================
*/
int idPhysics_Actor::GetTouchEnt( int i ) const {
if ( i < 0 || i >= numTouch ) {
return ENTITYNUM_NONE;
}
return touchEnts[i];
}
/*
===============
idPhysics_Actor::ResetNumTouchEnt
HUMANHEAD nla
===============
*/
void idPhysics_Actor::ResetNumTouchEnt( int i ) {
numTouch = i;
}
/*
================
hhPhysics_Player::HadGroundContacts
HUMANHEAD: aob
================
*/
bool idPhysics_Actor::HadGroundContacts() const {
return hadGroundContacts;
}
/*
================
idPhysics_Actor::HadGroundContacts
HUMANHEAD: aob
================
*/
void idPhysics_Actor::HadGroundContacts( const bool hadGroundContacts ) {
this->hadGroundContacts = hadGroundContacts;
}
/*
================
idPhysics_Actor::InterativeRotateMove
HUMANHEAD: aob
================
*/
bool idPhysics_Actor::IterativeRotateMove( const idVec3& upVector, const idVec3& idealUpVector, const idVec3& rotationOrigin, const idVec3& rotationCheckOrigin, int numIterations) {
trace_t rotationTraceInfo;
trace_t translationTraceInfo;
idRotation rotator;
idVec3 rotationVector;
const idVec3 origPos( rotationOrigin );
idVec3 currentOrigin( rotationOrigin );
idMat3 currentAxis( GetAxis() );
idVec3 averageTranslationVector( vec3_origin );
float numTranslationVectors = 0.0f;
if( idealUpVector.Compare(vec3_origin, VECTOR_EPSILON) ) {// For Zero G
return false;
}
if( upVector.Compare(idealUpVector, VECTOR_EPSILON) ) {
return false;
}
rotator.SetVec( DetermineRotationVector(upVector, idealUpVector, rotationCheckOrigin) );
rotator.SetAngle( RAD2DEG(idMath::ACos(upVector * idealUpVector)) );
rotator.ToMat3();
do {
rotator.SetOrigin( currentOrigin );
gameLocal.clip.Rotation( rotationTraceInfo, currentOrigin, rotator, clipModel, currentAxis, clipMask, self );
currentAxis = rotationTraceInfo.endAxis;
if( rotationTraceInfo.fraction < 1.0f ) {
gameLocal.clip.Translation( translationTraceInfo, currentOrigin, currentOrigin + rotationTraceInfo.c.normal * p_iterRotMoveTransDist.GetFloat(), clipModel, currentAxis, clipMask, self );
currentOrigin = translationTraceInfo.endpos;
averageTranslationVector += rotationTraceInfo.c.normal;
numTranslationVectors += 1.0f;
}
} while( --numIterations && rotationTraceInfo.fraction < 1.0f );
if( numTranslationVectors > 0.0f ) {
averageTranslationVector /= numTranslationVectors;
averageTranslationVector.Normalize();
gameLocal.clip.Translation( translationTraceInfo, currentOrigin, currentOrigin + -averageTranslationVector * p_iterRotMoveTransDist.GetFloat(), clipModel, currentAxis, clipMask, self );
currentOrigin = translationTraceInfo.endpos;
}
//HUMANHEAD rww - do a translation test before using this origin/axis
if (!gameLocal.clip.Translation( translationTraceInfo, currentOrigin, currentOrigin, clipModel, currentAxis, clipMask, self )) {
SetOrigin( currentOrigin );
SetAxis( currentAxis );
}
else { //HUMANHEAD rww - if we fail, try instantly rotating to the desired orientation
//HUMANHEAD PCF mdl 04/30/06 - Added LAST_MINUTE_HACK in case we want to revert this
#ifndef LAST_MINUTE_HACK
if (groundTrace.fraction < 1.0f && fabsf(DotProduct(idealUpVector, groundTrace.c.normal)) > 0.8f) { //hitting ground
const float fudge = 1.0f;
currentOrigin = rotationCheckOrigin + (groundTrace.c.normal*(fabsf(GetBounds()[0].z)+fudge));
idMat3 m = idealUpVector.ToMat3();
currentAxis[0] = m[2];
currentAxis[2] = m[0];
currentAxis[1] = m[0].Cross(m[2]);
if (!gameLocal.clip.Translation( translationTraceInfo, currentOrigin, currentOrigin, clipModel, currentAxis, clipMask, self )) {
SetOrigin( currentOrigin );
SetAxis( currentAxis );
}
}
#else
if (groundTrace.fraction < 1.0f && fabsf(DotProduct(idealUpVector, groundTrace.c.normal)) > 0.8f) { //hitting ground
const float fudge = 1.0f;
float safeD = (fabsf(GetBounds()[0].z)+fudge);
currentOrigin = rotationCheckOrigin + (groundTrace.c.normal*safeD);
idMat3 m = idealUpVector.ToMat3();
currentAxis[0] = m[2];
currentAxis[2] = m[0];
currentAxis[1] = m[0].Cross(m[2]);
if (!gameLocal.clip.Translation( translationTraceInfo, currentOrigin, currentOrigin, clipModel, currentAxis, clipMask, self )) {
//HUMANHEAD PCF rww 04/30/06 - trace back down on the normal once we have made sure we have a safe spot.
const float downFudge = 16.0f;
safeD = (fabsf(GetBounds()[1].z)+downFudge);
idVec3 backDown = currentOrigin - (groundTrace.c.normal*safeD);
gameLocal.clip.Translation( translationTraceInfo, currentOrigin, backDown, clipModel, currentAxis, clipMask, self );
SetOrigin( translationTraceInfo.endpos );
SetAxis( translationTraceInfo.endAxis );
}
}
#endif // LAST_MINUTE_HACK
}
return true;
}
/*
=============
idPhysics_Actor::DetermineRotationVector
HUMANHEAD: aob
=============
*/
idVec3 idPhysics_Actor::DetermineRotationVector( const idVec3& upVector, const idVec3& idealUpVector, const idVec3& checkOrigin ) {
idVec3 rotationVector = idealUpVector.Cross( upVector );
if( rotationVector.LengthSqr() <= VECTOR_EPSILON ) {
BuildRotationTraceDirectionTable( self->GetAxis() );//Actors return viewAxis and plain entities return physics axis
for( int iIndex = 0; iIndex < c_iNumRotationTraces; ++iIndex ) {
if( DirectionIsClear(checkOrigin, rotationTraceDirectionTable[iIndex]) ) {
rotationVector = rotationTraceDirectionTable[iIndex];
break;
}
}
}
rotationVector.Normalize();
return rotationVector;
}
/*
=============
idPhysics_Actor::DirectionIsClear
HUMANHEAD: aob
=============
*/
#define ROTATION_TRACE_DISTANCE ((pm_bboxwidth.GetFloat() * 0.5f) + 10.0f)
bool idPhysics_Actor::DirectionIsClear( const idVec3& checkOrigin, const idVec3& direction ) {
trace_t traceInfo;
gameLocal.clip.TracePoint( traceInfo, checkOrigin, checkOrigin + direction * ROTATION_TRACE_DISTANCE, clipMask, self );
return (traceInfo.fraction == 1.0f);
}
/*
=============
idPhysics_Actor::BuildRotationTraceDirectionTable
HUMANHEAD: aob
=============
*/
void idPhysics_Actor::BuildRotationTraceDirectionTable( const idMat3& Axis ) {
rotationTraceDirectionTable[0] = Axis[0];
rotationTraceDirectionTable[1] = -Axis[0];
rotationTraceDirectionTable[2] = Axis[1];
rotationTraceDirectionTable[3] = -Axis[1];
}
+133
View File
@@ -0,0 +1,133 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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.
===================================================================================
*/
//HUMANHEAD
#define MAXTOUCH 32
const int c_iNumRotationTraces = 4;
//HUMANHEAD END
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 );
//HUMANHEAD nla
int GetNumTouchEnts( void ) const;
int GetTouchEnt( int i ) const;
void ResetNumTouchEnt( int i );
// HUMANHEAD END
//HUMANHEAD: aob - added
const trace_t& GetGroundTrace() const { return groundTrace; }
virtual const idMaterial* GetGroundMaterial() const { if(!HasGroundContacts()) return NULL; return groundTrace.c.material; } // JRM - return NULL if no gc's
surfTypes_t GetGroundMatterType() const { return gameLocal.GetMatterType(groundTrace); }
const int GetGroundSurfaceFlags() const { const idMaterial* mat = GetGroundMaterial(); if( mat ) { return mat->GetSurfaceFlags(); } else { return 0; } }
bool HadGroundContacts() const;
virtual void HadGroundContacts( const bool hadGroundContacts );
//HUMANHEAD 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 IsPushable( void ) const;
const idVec3 & GetOrigin( int id = 0 ) const;
const idMat3 & GetAxis( int id = 0 ) const;
virtual // HUMANHEAD jsh made virtual
void SetGravity( const idVec3 &newGravity );
const idMat3 & GetGravityAxis( 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 );
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;
//HUMANHEAD: aob
trace_t groundTrace;
//HUMANHEAD END
//HUMANHEAD nla
// entities touched during last evaluate
int numTouch;
int touchEnts[MAXTOUCH];
void AddTouchEnt( int entityNum );
void AddTouchEntList( idList<int> &list );
bool hadGroundContacts;
idVec3 rotationTraceDirectionTable[ c_iNumRotationTraces ];
// HUMANHEAD END
// results of last evaluate
idEntityPtr<idEntity> groundEntityPtr;
//HUMANHEAD: aob
protected:
virtual bool IterativeRotateMove( const idVec3& upVector, const idVec3& idealUpVector, const idVec3& rotationOrigin, const idVec3& rotationCheckOrigin, int numIterations );
idVec3 DetermineRotationVector( const idVec3& upVector, const idVec3& idealUpVector, const idVec3& rotationOrigin );
bool DirectionIsClear( const idVec3& checkOrigin, const idVec3& direction );
void BuildRotationTraceDirectionTable( const idMat3& Axis );
//HUMANHEAD END
};
#endif /* !__PHYSICS_ACTOR_H__ */
+844
View File
@@ -0,0 +1,844 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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;
}
/*
================
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;
}
/*
================
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;
}
}
}
/*
================
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::HasContacts
HUMANHEAD: aob
================
*/
bool idPhysics_Base::HasContacts( void ) const {
return contacts.Num() > 0;
}
/*
================
idPhysics_Base::GetGroundContactNormal
HUMANHEAD: aob
================
*/
idVec3 idPhysics_Base::GetGroundContactNormal() const {
idVec3 contactNormal;
// HUMANHEAD PCF pdm 05-10-06: Bugfix from Venom, Initialize before use
contactNormal.Zero();
for( int ix = contacts.Num() - 1; ix >= 0; --ix ) {
contactNormal += contacts[ix].normal;
}
contactNormal.Normalize();
return contactNormal;
}
/*
================
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;
num = gameLocal.clip.Contacts( &contacts[index], 10, clipModel->GetOrigin(),
dir, CONTACT_EPSILON, clipModel, clipModel->GetAxis(), clipMask, self );
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 {
if ( !gameLocal.clip.GetWorldBounds().Expand( 128.0f ).IntersectsBounds( GetAbsBounds() ) ) {
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 ) {
}
+145
View File
@@ -0,0 +1,145 @@
// Copyright (C) 2004 Id Software, Inc.
//
#ifndef __PHYSICS_BASE_H__
#define __PHYSICS_BASE_H__
/*
===============================================================================
Physics base for a moving object using one or more collision models.
===============================================================================
*/
#define contactEntity_t idEntityPtr<idEntity>
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 );
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;
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;
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;
//HUMANHEAD: aob
bool HasContacts( void ) const;
idVec3 GetGroundContactNormal() const;
//HUMANHEAD END
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__ */
+809
View File
@@ -0,0 +1,809 @@
// Copyright (C) 2004 Id Software, Inc.
//
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
CLASS_DECLARATION( idPhysics_Actor, idPhysics_Monster )
END_CLASS
// HUMANHEAD PDM: This now declared in physics_player.h, so not needed here
//const float OVERCLIP = 1.001f;
/*
=====================
idPhysics_Monster::CheckGround
=====================
*/
void idPhysics_Monster::CheckGround( monsterPState_t &state ) {
// HUMANHEAD aob: groundTrace is now stored on object
// trace_t groundTrace;
idVec3 down;
if ( gravityNormal == vec3_zero ) {
state.onGround = false;
groundEntityPtr = NULL;
return;
}
down = state.origin + gravityNormal * CONTACT_EPSILON;
gameLocal.clip.Translation( groundTrace, state.origin, down, clipModel, clipModel->GetAxis(), clipMask, self );
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, idList<int> *touched ) {
int i;
trace_t tr;
idVec3 move;
blockingEntity = NULL;
move = delta;
for( i = 0; i < 3; i++ ) {
gameLocal.clip.Translation( tr, start, start + move, clipModel, clipModel->GetAxis(), clipMask, self );
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;
idList<int> noStepEntities, stepEntities; // HUMANHEAD nla
if ( delta == vec3_origin ) {
return MM_OK;
}
// try to move without stepping up
noStepPos = start;
noStepVel = velocity;
result1 = SlideMove( noStepPos, noStepVel, delta, &noStepEntities );
if ( result1 == MM_OK ) {
AddTouchEntList( noStepEntities ); // HUMANHEAD nla
velocity = noStepVel;
if ( gravityNormal == vec3_zero ) {
start = noStepPos;
return MM_OK;
}
//! Check block below for requirment of any touch entities
// try to step down so that we walk down slopes and stairs at a normal rate
down = noStepPos + gravityNormal * maxStepHeight;
gameLocal.clip.Translation( tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
if ( tr.fraction < 1.0f ) {
start = tr.endpos;
return MM_STEPPED;
} else {
start = noStepPos;
return MM_OK;
}
}
if ( blockingEntity && blockingEntity->IsType( idActor::Type ) ) {
// try to step down in case walking into an actor while going down steps
down = noStepPos + gravityNormal * maxStepHeight;
gameLocal.clip.Translation( tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
start = tr.endpos;
velocity = noStepVel;
return MM_BLOCKED;
}
if ( gravityNormal == vec3_zero ) {
return result1;
}
// try to step up
up = start - gravityNormal * maxStepHeight;
gameLocal.clip.Translation( tr, start, up, clipModel, clipModel->GetAxis(), clipMask, self );
if ( tr.fraction == 0.0f ) {
AddTouchEntList( noStepEntities ); // HUMANHEAD nla
start = noStepPos;
velocity = noStepVel;
return result1;
}
//HUMANHEAD nla - Add the entity touched
if (tr.fraction < 1.0f) {
stepEntities.Append( tr.c.entityNum );
}
// try to move at the stepped up position
stepPos = tr.endpos;
stepVel = velocity;
result2 = SlideMove( stepPos, stepVel, delta );
if ( result2 == MM_BLOCKED ) {
AddTouchEntList( noStepEntities ); // HUMANHEAD nla
start = noStepPos;
velocity = noStepVel;
return result1;
}
// step down again
down = stepPos + gravityNormal * maxStepHeight;
gameLocal.clip.Translation( tr, stepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
stepPos = tr.endpos;
//HUMANHEAD nla - Add the entity touched
if (tr.fraction < 1.0f) {
stepEntities.Append( tr.c.entityNum );
}
// 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 ) ) {
AddTouchEntList( noStepEntities ); // HUMANHEAD nla
start = noStepPos;
velocity = noStepVel;
return MM_SLIDING;
}
AddTouchEntList( stepEntities ); // HUMANHEAD nla
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( &current, 0, sizeof( current ) );
current.atRest = -1;
saved = current;
delta.Zero();
maxStepHeight = 22.0f; // JRM CHANGED FROM 18
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->WriteVec3( state.origin );
savefile->WriteVec3( state.velocity );
savefile->WriteVec3( state.localOrigin );
savefile->WriteVec3( state.pushVelocity );
savefile->WriteBool( state.onGround );
savefile->WriteInt( state.atRest );
}
/*
================
idPhysics_Monster_RestorePState
================
*/
void idPhysics_Monster_RestorePState( idRestoreGame *savefile, monsterPState_t &state ) {
savefile->ReadVec3( state.origin );
savefile->ReadVec3( state.velocity );
savefile->ReadVec3( state.localOrigin );
savefile->ReadVec3( state.pushVelocity );
savefile->ReadBool( state.onGround );
savefile->ReadInt( state.atRest );
}
/*
================
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
================
*/
// HUMANHEAD AOB: PERSISTANT NOTIFY
bool idPhysics_Monster::Evaluate( int timeStepMSec, int endTimeMSec ) {
PROFILE_SCOPE("Monster", PROFMASK_PHYSICS);
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;
clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() );
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 false;
}
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
moveResult = idPhysics_Monster::StepMove( current.origin, current.velocity, delta );
delta.Zero();
}
}
clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() );
// get all the ground contacts
EvaluateContacts();
// move the monster velocity back into the world frame
current.velocity += 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();
}
return ( current.origin != oldOrigin );
}
/*
================
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;
clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() );
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;
}
clipModel->Link( gameLocal.clip, self, 0, newOrigin, clipModel->GetAxis() );
Activate();
}
/*
================
idPhysics_Player::SetAxis
================
*/
void idPhysics_Monster::SetAxis( const idMat3 &newAxis, int id ) {
clipModel->Link( gameLocal.clip, self, 0, clipModel->GetOrigin(), newAxis );
Activate();
}
/*
================
idPhysics_Monster::Translate
================
*/
void idPhysics_Monster::Translate( const idVec3 &translation, int id ) {
current.localOrigin += translation;
current.origin += translation;
clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() );
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;
}
clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() * rotation.ToMat3() );
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.pushVelocity;
}
/*
================
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();
}
}
}
// HUMANHEAD pdm: weren't implemented before, just stubbed out
void idPhysics_Monster::SetMinFloorCosine( const float newMinFloorCosine ) {
minFloorCosine = newMinFloorCosine;
}
// HUMANHEAD END
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;
}
+129
View File
@@ -0,0 +1,129 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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;
} 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 );
idVec3 GetDelta(void) const {return delta;} // HUMANHEAD JRM
// 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 );
protected://HUMANHEAD: aob
// 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;
protected://HUMANHEAD: aob
void CheckGround( monsterPState_t &state );
virtual//HUMANHEAD: aob
monsterMoveResult_t SlideMove( idVec3 &start, idVec3 &velocity, const idVec3 &delta, idList<int> *touched = NULL );
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
+160
View File
@@ -0,0 +1,160 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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
// HUMANHEAD mdl: Added these for accumulating spline angle changes. They are NULL when splines are inactive.
idAngles * lastSplineAngles; // If not NULL, The spline angles from the last Evaluate() call
idMat3 * deltaSplineAngles; // If not NULL, the difference between current.angle and the initial spline angles when SetSpline is called.
idMat3 * deltaSplineAnglesInverse; // If not NULL, deltaSplineAngles.Inverse()
// HUMANHEAD END
} 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;
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;
//HUMANHEAD: aob
const idAngles &GetCurrentAngularSpeed( int id = 0 ) const;
//HUMANHEAD END
void WriteToSnapshot( idBitMsgDelta &msg ) const;
void ReadFromSnapshot( const idBitMsgDelta &msg );
protected: // HUMANHEAD nla
// 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;
private:
bool TestIfAtRest( void ) const;
void Rest( void );
};
#endif /* !__PHYSICS_PARAMETRIC_H__ */
File diff suppressed because it is too large Load Diff
+220
View File
@@ -0,0 +1,220 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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.
===================================================================================
*/
//HUMANHEAD START: All these moved here from physics_player.cpp
// movement parameters
const float PM_STOPSPEED = 100.0f;
const float PM_SWIMSCALE = 0.5f;
const float PM_LADDERSPEED = 100.0f;
const float PM_STEPSCALE = 1.0f;
const float PM_ACCELERATE = 10.0f;
const float PM_AIRACCELERATE = 1.0f;
const float PM_WATERACCELERATE = 4.0f;
const float PM_FLYACCELERATE = 8.0f;
const float PM_FRICTION = 6.0f;
const float PM_AIRFRICTION = 0.0f;
const float PM_WATERFRICTION = 1.0f;
const float PM_FLYFRICTION = 3.0f;
const float PM_NOCLIPFRICTION = 12.0f;
const float MIN_WALK_NORMAL = 0.7f; // can't walk on very steep slopes
const float OVERCLIP = 1.001f;
// movementFlags
const int PMF_DUCKED = 1; // set when ducking
const int PMF_JUMPED = 2; // set when the player jumped this frame
const int PMF_STEPPED_UP = 4; // set when the player stepped up this frame
const int PMF_STEPPED_DOWN = 8; // set when the player stepped down this frame
const int PMF_JUMP_HELD = 16; // set when jump button is held down
const int PMF_TIME_LAND = 32; // movementTime is time before rejump
const int PMF_TIME_KNOCKBACK = 64; // movementTime is an air-accelerate only time
const int PMF_TIME_WATERJUMP = 128; // movementTime is waterjump
const int PMF_ALL_TIMES = (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK);
//HUMANHEAD END
// 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;
typedef struct playerPState_s {
idVec3 origin;
//HUMANHEAD: aob - needed for saving state and vehicles
idMat3 axis;
idMat3 localAxis;
//HUMANHEAD END
idVec3 velocity;
idVec3 localOrigin;
idVec3 pushVelocity;
float stepUp;
int movementType;
int movementFlags;
int movementTime;
} 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 );
virtual //HUMANHEAD: Made virtual
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;
virtual //HUMANHEAD: Made virtual
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 );
protected: //HUMANHEAD
// 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;
//HUMANHEAD: aob - moved to idPhysics_Actor
// trace_t groundTrace;
//HUMANHEAD END
const idMaterial * groundMaterial;
// ladder movement
bool ladder;
idVec3 ladderNormal;
// results of last evaluate
waterLevel_t waterLevel;
int waterType;
idVec3 wishdir; //HUMANHEAD
protected://HUMANHEAD
// HUMANHEAD
virtual idVec3 DetermineJumpVelocity();
// HUMANHEAD END
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 );
virtual //HUMANHEAD: Made virtual
void AirMove( void );
virtual //HUMANHEAD: Made virtual
void WalkMove( void );
void DeadMove( void );
void NoclipMove( void );
void SpectatorMove( void );
void LadderMove( void );
void CorrectAllSolid( trace_t &trace, int contents );
virtual //HUMANHEAD: Made virtual
void CheckGround( void );
void CheckDuck( void );
void CheckLadder( void );
bool CheckJump( void );
bool CheckWaterJump( void );
void SetWaterLevel( void );
void DropTimers( void );
void MovePlayer( int msec );
};
#endif /* !__PHYSICS_PLAYER_H__ */
File diff suppressed because it is too large Load Diff
+122
View File
@@ -0,0 +1,122 @@
#ifndef __HH_PHYSICS_PLAYER_H
#define __HH_PHYSICS_PLAYER_H
/**********************************************************************
hhPhysics_Player
**********************************************************************/
const int c_iNumWallwalkTraces = 5;
class hhPhysics_Player: public idPhysics_Player
{
CLASS_PROTOTYPE( hhPhysics_Player );
public:
hhPhysics_Player( void );
virtual bool Evaluate( int timeStepMSec, int endTimeMSec );
virtual void SetSelf( idEntity *e );
virtual void SaveState( void );
virtual void RestoreState( void );
void WriteToSnapshot( idBitMsgDelta &msg, bool inVehicle ) const;
void ReadFromSnapshot( const idBitMsgDelta &msg, bool inVehicle );
bool IsWallWalking() const { return isWallWalking; }
bool WasWallWalking() const { return wasWallWalking; }
void IsWallWalking( bool wallwalking ) { isWallWalking = wallwalking; }
void WasWallWalking( bool wallwalking ) { wasWallWalking = wallwalking; }
bool AlignedWithGravity() const;
bool ShouldSlopeCheck() const { return bDoSlopeCheck && !isWallWalking; }
void SetSlopeCheck( bool on ) { bDoSlopeCheck = on; }
void SetInwardGravity(int inwardGravity); //rww
bool IsInwardGravity() const { return iInwardGravity > 0; } //rww
virtual void ShouldRemainAlignedToAxial( const bool remainAligned );
virtual bool ShouldRemainAlignedToAxial() const;
virtual void OrientToGravity( bool orientToGravity );
virtual bool OrientToGravity() const;
virtual void Translate( const idVec3 &translation, int id = 0 );
virtual void Rotate( const idRotation& rotation, int id = 0 );
virtual const idVec3& GetOrigin( int id = 0 ) const;
virtual const idMat3& GetAxis( int id = 0 ) const;
virtual void SetOrigin( const idVec3 &newOrigin, int id = 0 );
virtual void SetAxis( const idMat3 &newAxis, int id = 0 );
virtual void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
virtual void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
virtual bool IsGroundEntity( int entityNum ) const;
virtual bool IsGroundClipModel( int entityNum, int id = 0 ) const;
virtual bool HasGroundContacts( void ) const;
virtual bool ExtraGroundCheck(idClipModel *customClipModel = NULL); //HUMANHEAD rww
virtual void AddGroundContacts( const idClipModel *clipModel );
virtual bool EvaluateContacts( void );
virtual void SetKnockBack( const int knockBackTime );
virtual void SetPushed( int deltaTime );
virtual void ForceMovedFrame(bool forceMoved) { bMoveNextFrame = forceMoved; } //HUMANHEAD rww
virtual void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
virtual bool WallWalkIsAllowed() const;
void CheckWallWalk( bool bForce = false );
virtual void CheckGround();
virtual const idMaterial* GetGroundMaterial() const { return groundMaterial; }
playerPState_t& GetPlayerState() { return current; }
virtual void ForceCrouching();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
protected:
idVec3 ClipModelRotationOrigin;
bool shouldRemainAlignedToAxial;
bool orientToGravity;
bool isWallWalking;
bool wasWallWalking;
idVec3 oldOrigin;
idMat3 oldAxis;
bool bDoSlopeCheck;
int iInwardGravity; //rww - number of inward gravity zones player is in
//HUMANHEAD PCF rww 05/11/06 - hack fix for stuck bugs
int stuckCount;
idVec3 stuckOrigin;
//HUMANHEAD END
hhCameraInterpolator* camera;
hhPlayer* castSelf;
idEntity* castSelfGeneric; //rww
idVec3 wallwalkTraceOriginTable[ c_iNumWallwalkTraces ];
bool bMoveNextFrame; //HUMANHEAD rww
protected:
void EvaluateOwnerCamera( const int timeStep );
void SetOwnerCameraTarget( const idVec3& Origin, const idMat3& Axis, int iInterpFlags );
void LinkClip( const idVec3& Origin, const idMat3& Axis );
virtual idVec3 DetermineJumpVelocity();
void BuildWallwalkTraceOriginTable( const idMat3& Axis );
void PerformGroundTrace( trace_t& TraceInfo, const idVec3& Start );
bool EvaluateGroundTrace( const trace_t& TraceInfo );
virtual bool IterativeRotateMove( const idVec3& UpVector, const idVec3& IdealUpVector, const idVec3& RotationOrigin, const idVec3& RotationCheckOrigin, int iNumIterations );
bool RotateMove( const idVec3& UpVector, const idVec3& IdealUpVector, const idVec3& RotationOrigin, const idVec3& RotationCheckOrigin );
void TranslateMove( const idVec3& TranslationVector, const float fDist );
virtual void WalkMove();
virtual void AirMove();
float GetContactEpsilon(void) const;
};
#endif
File diff suppressed because it is too large Load Diff
+179
View File
@@ -0,0 +1,179 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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.
===================================================================================
*/
extern const float RB_VELOCITY_MAX;
extern const int RB_VELOCITY_TOTAL_BITS;
extern const int RB_VELOCITY_EXPONENT_BITS;
extern const int RB_VELOCITY_MANTISSA_BITS;
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;
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 );
//HUMANHEAD: aob
const idVec3& GetCenterOfMass() const { return centerOfMass; }
protected: // HUMANHEAD
// state of the rigid body
rigidBodyPState_t current;
rigidBodyPState_t saved;
// 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;
protected: // HUMANHEAD
friend void RigidBodyDerivatives( const float t, const void *clientData, const float *state, float *derivatives );
virtual // HUMANHEAD: made virtual
void Integrate( const float deltaTime, rigidBodyPState_t &next );
virtual // HUMANHEAD: made virtual
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 );
// HUMANHEAD pdm: testing
void TestForRotation(const char *text);
// HUMANHEAD pdm: testing
};
#endif /* !__PHYSICS_RIGIDBODY_H__ */
+836
View File
@@ -0,0 +1,836 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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 ) {
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
}
}
/*
================
idPhysics_Static::GetClipModel
================
*/
idClipModel *idPhysics_Static::GetClipModel( int id ) const {
if ( clipModel ) {
return clipModel;
}
return gameLocal.clip.DefaultClipModel();
}
/*
================
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;
}
/*
================
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 ) {
PROFILE_SCOPE("Static", PROFMASK_PHYSICS);
idVec3 masterOrigin, oldOrigin;
idMat3 masterAxis, oldAxis;
if ( hasMaster ) {
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 ) {
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
}
return ( current.origin != oldOrigin || current.axis != oldAxis );
}
// HUMANHEAD pdm: Statics occasionally get physics activated by things binding to them.
// Allow this, but immediately become inactive again since we can't move unless bound to something else.
if (self->IsActive(TH_PHYSICS)) {
self->BecomeInactive( TH_PHYSICS );
}
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;
}
/*
================
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 ) {
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
}
}
/*
================
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 ) {
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
}
}
/*
================
idPhysics_Static::Translate
================
*/
void idPhysics_Static::Translate( const idVec3 &translation, int id ) {
current.localOrigin += translation;
current.origin += translation;
if ( clipModel ) {
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
}
}
/*
================
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 ) {
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
}
}
/*
================
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() );
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 ) {
gameLocal.clip.TranslationModel( results, current.origin, current.origin + translation,
clipModel, current.axis, MASK_SOLID, model->Handle(), model->GetOrigin(), model->GetAxis() );
} else {
gameLocal.clip.Translation( results, current.origin, current.origin + translation,
clipModel, current.axis, MASK_SOLID, self );
}
}
/*
================
idPhysics_Static::ClipRotation
================
*/
void idPhysics_Static::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
if ( model ) {
gameLocal.clip.RotationModel( results, current.origin, rotation,
clipModel, current.axis, MASK_SOLID, model->Handle(), model->GetOrigin(), model->GetAxis() );
} else {
gameLocal.clip.Rotation( results, current.origin, rotation, clipModel, current.axis, MASK_SOLID, self );
}
}
/*
================
idPhysics_Static::ClipContents
================
*/
int idPhysics_Static::ClipContents( const idClipModel *model ) const {
if ( clipModel ) {
if ( model ) {
return gameLocal.clip.ContentsModel( clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1,
model->Handle(), model->GetOrigin(), model->GetAxis() );
} else {
return gameLocal.clip.Contents( clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1, NULL );
}
}
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 ) {
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
}
}
/*
================
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();
}
//HUMANHEAD rww
/*
================
idPhysics_Static::GetPState
================
*/
staticPState_t *idPhysics_Static::GetPState(void) {
return &current;
}
//HUMANHEAD END
+136
View File
@@ -0,0 +1,136 @@
// Copyright (C) 2004 Id Software, Inc.
//
#ifndef __PHYSICS_STATIC_H__
#define __PHYSICS_STATIC_H__
/*
===============================================================================
Physics for a non moving object using at most one collision model.
===============================================================================
*/
typedef struct staticPState_s {
idVec3 origin;
idMat3 axis;
idVec3 localOrigin;
idMat3 localAxis;
} staticPState_t;
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 );
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;
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;
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 );
//HUMANHEAD rww - sorry, need access for snapshot code (better than making multiple snapshot functions)
virtual staticPState_t *GetPState(void);
//HUMANHEAD END
protected:
idEntity * self; // entity using this physics object
staticPState_t current; // physics state
idClipModel * clipModel; // collision model
// master
bool hasMaster;
bool isOrientated;
};
#endif /* !__PHYSICS_STATIC_H__ */
File diff suppressed because it is too large Load Diff
+129
View File
@@ -0,0 +1,129 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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 );
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;
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;
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
idList<staticPState_t> current; // physics state
idList<idClipModel *> clipModels; // collision model
// master
bool hasMaster;
bool isOrientated;
};
#endif /* !__PHYSICS_STATICMULTI_H__ */
File diff suppressed because it is too large Load Diff
+91
View File
@@ -0,0 +1,91 @@
// Copyright (C) 2004 Id Software, Inc.
//
#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
// HUMANHEAD nla - Used to fix ragdolls colliding with movers when on them.
#define PUSHFL_UNBLOCKABLE 128 // can not be blocked
// HUMANHEAD END
//#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__ */