1151 lines
26 KiB
C++
1151 lines
26 KiB
C++
|
// Copyright (C) 2007 Id Software, Inc.
|
||
|
//
|
||
|
|
||
|
#include "../precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
#include "Physics_Base.h"
|
||
|
#include "../Entity.h"
|
||
|
#include "Force.h"
|
||
|
|
||
|
#if !defined( _XENON ) && !defined( MONOLITHIC )
|
||
|
idCVar r_debugAxisLength( "r_debugAxisLength", "2", CVAR_RENDERER, "used to set the length of drawn debug axis" );
|
||
|
#else
|
||
|
extern idCVar r_debugAxisLength;
|
||
|
#endif
|
||
|
|
||
|
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::SetSelf
|
||
|
================
|
||
|
*/
|
||
|
void idPhysics_Base::SetSelf( idEntity *e ) {
|
||
|
assert( e );
|
||
|
self = e;
|
||
|
traceCollection.SetSelf( 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::AddTorque
|
||
|
================
|
||
|
*/
|
||
|
void idPhysics_Base::AddTorque( const idVec3& torque ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idPhysics_Base::AddForce
|
||
|
================
|
||
|
*/
|
||
|
void idPhysics_Base::AddForce( 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::UnlinkClip
|
||
|
================
|
||
|
*/
|
||
|
void idPhysics_Base::UnlinkClip( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idPhysics_Base::LinkClip
|
||
|
================
|
||
|
*/
|
||
|
void idPhysics_Base::LinkClip( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idPhysics_Base::DisableClip
|
||
|
================
|
||
|
*/
|
||
|
void idPhysics_Base::DisableClip( bool activateContacting ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idPhysics_Base::EnableClip
|
||
|
================
|
||
|
*/
|
||
|
void idPhysics_Base::EnableClip( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idPhysics_Base::EvaluateContacts
|
||
|
================
|
||
|
*/
|
||
|
bool idPhysics_Base::EvaluateContacts( CLIP_DEBUG_PARMS_DECLARATION_ONLY ) {
|
||
|
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::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( CLIP_DEBUG_PARMS_DECLARATION const idClipModel *clipModel, unsigned int max ) {
|
||
|
assert( max > 0 );
|
||
|
|
||
|
int index = contacts.Num();
|
||
|
contacts.SetNum( index + max, false );
|
||
|
|
||
|
idVec3 dir = gravityNormal;
|
||
|
// int num = GetTraceCollection().Contacts( CLIP_DEBUG_PARMS_PASSTHRU &contacts[index], max, clipModel->GetOrigin(),
|
||
|
// &dir, CONTACT_EPSILON, clipModel, clipModel->GetAxis(), clipMask );
|
||
|
// contacts.SetNum( index + num, false );
|
||
|
|
||
|
trace_t tr;
|
||
|
idVec3 start = clipModel->GetOrigin() - dir * CONTACT_EPSILON;
|
||
|
idVec3 end = start + dir * CONTACT_EPSILON * 2.0f;
|
||
|
GetTraceCollection().Translation( CLIP_DEBUG_PARMS_PASSTHRU tr, start, end, clipModel, clipModel->GetAxis(), clipMask );
|
||
|
if ( tr.fraction < 1.0f ) {
|
||
|
contacts.SetNum( index + 1, false );
|
||
|
contacts[ index ] = tr.c;
|
||
|
} else {
|
||
|
contacts.SetNum( index, 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();
|
||
|
} 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, r_debugAxisLength.GetInteger() );
|
||
|
}
|
||
|
|
||
|
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, r_debugAxisLength.GetInteger() );
|
||
|
start = end;
|
||
|
}
|
||
|
end = org + idRotation( vec3_origin, dir, -length ).ToMat3() * vec;
|
||
|
gameRenderWorld->DebugArrow( colorBlue, start, end, r_debugAxisLength.GetInteger() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idPhysics_Base::GetTraceCollection
|
||
|
================
|
||
|
*/
|
||
|
const sdClipModelCollection& idPhysics_Base::GetTraceCollection( void ) {
|
||
|
if ( g_useTraceCollection.GetBool() ) {
|
||
|
traceCollection.Update( GetBounds(), GetOrigin(), GetAxis(), GetLinearVelocity(),
|
||
|
GetAngularVelocity(), GetClipMask(), self );
|
||
|
}
|
||
|
return traceCollection;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::SetSelf
|
||
|
============
|
||
|
*/
|
||
|
void sdClipModelCollection::SetSelf( idEntity* e ) {
|
||
|
assert( e );
|
||
|
self = e;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::Update
|
||
|
============
|
||
|
*/
|
||
|
void sdClipModelCollection::Update( const idBounds& bounds, const idVec3& origin, const idMat3& axis,
|
||
|
const idVec3& linearVelocity, const idVec3& angularVelocity,
|
||
|
int clipMask, idEntity* passEntity ) {
|
||
|
|
||
|
if ( gameLocal.time != lastUpdate ) {
|
||
|
// construct a bounds from the movement
|
||
|
idBounds currentBounds;
|
||
|
currentBounds.FromTransformedBounds( bounds, origin, axis );
|
||
|
|
||
|
// estimate future position & orientation
|
||
|
float timeStep = MS2SEC( gameLocal.msec );
|
||
|
idVec3 futurePosition = origin + linearVelocity * timeStep;
|
||
|
idVec3 angDelta = angularVelocity * timeStep;
|
||
|
idVec3 rotationAxis = angDelta;
|
||
|
float rotationAngle = RAD2DEG( rotationAxis.Normalize() );
|
||
|
idRotation rotation( vec3_origin, rotationAxis, rotationAngle );
|
||
|
idMat3 futureOrientation = axis * rotation.ToMat3();
|
||
|
|
||
|
idBounds futureBounds;
|
||
|
futureBounds.FromTransformedBounds( bounds, futurePosition, futureOrientation );
|
||
|
|
||
|
idBounds totalBounds = currentBounds;
|
||
|
totalBounds.AddBounds( futureBounds );
|
||
|
|
||
|
// expand it a bit
|
||
|
totalBounds.ExpandSelf( 64.0f );
|
||
|
|
||
|
|
||
|
// find all the clipmodels touching the bounds (including the world)
|
||
|
collection.AssureSize( MAX_GENTITIES );
|
||
|
int num = gameLocal.clip.ClipModelsTouchingBounds( CLIP_DEBUG_PARMS totalBounds, clipMask, &collection.Front(), MAX_GENTITIES, passEntity, true );
|
||
|
collection.SetNum( num, false );
|
||
|
|
||
|
// gameRenderWorld->DebugBounds( colorRed, totalBounds );
|
||
|
}
|
||
|
|
||
|
lastUpdate = gameLocal.time;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::RemoveEntitiesOfCollection
|
||
|
============
|
||
|
*/
|
||
|
void sdClipModelCollection::RemoveEntitiesOfCollection( const char* collectionName ) {
|
||
|
const sdEntityCollection* entCollection = gameLocal.GetEntityCollection( collectionName );
|
||
|
if ( entCollection == NULL ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for ( int i = 0; i < collection.Num(); i++ ) {
|
||
|
const idClipModel* model = collection[ i ];
|
||
|
|
||
|
if ( model->GetEntity() == NULL ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( entCollection->Contains( model->GetEntity() ) ) {
|
||
|
collection.RemoveIndexFast( i );
|
||
|
i--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::ForceNextUpdate
|
||
|
============
|
||
|
*/
|
||
|
void sdClipModelCollection::ForceNextUpdate() {
|
||
|
lastUpdate = -1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::Translation
|
||
|
============
|
||
|
*/
|
||
|
bool sdClipModelCollection::TracePoint( CLIP_DEBUG_PARMS_DECLARATION trace_t &results, const idVec3 &start,
|
||
|
const idVec3 &end, int contentMask ) const {
|
||
|
return Translation( CLIP_DEBUG_PARMS_PASSTHRU results, start, end, NULL, mat3_identity, contentMask );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::Translation
|
||
|
============
|
||
|
*/
|
||
|
bool sdClipModelCollection::Translation( CLIP_DEBUG_PARMS_DECLARATION trace_t &results, const idVec3 &start, const idVec3 &end,
|
||
|
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask ) const {
|
||
|
|
||
|
if ( !g_useTraceCollection.GetBool() ) {
|
||
|
return gameLocal.clip.Translation( CLIP_DEBUG_PARMS_PASSTHRU results, start, end, mdl, trmAxis, contentMask, self );
|
||
|
}
|
||
|
|
||
|
// TWTODO: Add verification stuff to ensure no points of the clip model are outside the bounds that were checked over
|
||
|
|
||
|
idBounds traceBounds;
|
||
|
if ( mdl == NULL ) {
|
||
|
traceBounds.FromPointTranslation( start, end - start );
|
||
|
} else {
|
||
|
traceBounds.FromBoundsTranslation( mdl->GetBounds(), start, trmAxis, end - start );
|
||
|
}
|
||
|
traceBounds.ExpandSelf( CM_BOX_EPSILON );
|
||
|
|
||
|
results.fraction = 1.0f;
|
||
|
results.endpos = end;
|
||
|
results.endAxis = trmAxis;
|
||
|
for ( int i = 0; i < collection.Num(); i++ ) {
|
||
|
const idClipModel* model = collection[ i ];
|
||
|
|
||
|
bool isDead = false;
|
||
|
if ( model->GetEntity() == NULL ) {
|
||
|
if ( model->GetCollisionModel() != NULL ) {
|
||
|
isDead = !model->GetCollisionModel()->IsWorld();
|
||
|
} else {
|
||
|
isDead = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( isDead ) {
|
||
|
// the entity has been removed between updating the collection & now
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( !model->GetAbsBounds().IntersectsBounds( traceBounds ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( !( model->GetContents() & contentMask ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
trace_t trace;
|
||
|
gameLocal.clip.TranslationModel( CLIP_DEBUG_PARMS_PASSTHRU trace, start, end, mdl, trmAxis, contentMask, model, model->GetOrigin(), model->GetAxis() );
|
||
|
if ( trace.fraction < results.fraction ) {
|
||
|
results = trace;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( mdl != NULL ) {
|
||
|
results.c.selfId = mdl->GetId();
|
||
|
} else {
|
||
|
results.c.selfId = 0;
|
||
|
}
|
||
|
return ( results.fraction != 1.0f );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::Rotation
|
||
|
============
|
||
|
*/
|
||
|
bool sdClipModelCollection::Rotation( CLIP_DEBUG_PARMS_DECLARATION trace_t &results, const idVec3 &start, const idRotation &rotation,
|
||
|
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask ) const {
|
||
|
|
||
|
if ( !g_useTraceCollection.GetBool() ) {
|
||
|
return gameLocal.clip.Rotation( CLIP_DEBUG_PARMS_PASSTHRU results, start, rotation, mdl, trmAxis, contentMask, self );
|
||
|
}
|
||
|
|
||
|
// TWTODO: Add verification stuff to ensure no points of the clip model are outside the bounds that were checked over
|
||
|
|
||
|
idBounds traceBounds;
|
||
|
if ( mdl == NULL ) {
|
||
|
traceBounds.FromPointTranslation( start, vec3_origin );
|
||
|
} else {
|
||
|
traceBounds.FromBoundsTranslation( mdl->GetBounds(), start, trmAxis, vec3_origin );
|
||
|
}
|
||
|
traceBounds.ExpandSelf( CM_BOX_EPSILON );
|
||
|
|
||
|
results.fraction = 1.0f;
|
||
|
results.endpos = start;
|
||
|
results.endAxis = trmAxis * rotation.ToMat3();
|
||
|
rotation.RotatePoint( results.endpos );
|
||
|
|
||
|
for ( int i = 0; i < collection.Num(); i++ ) {
|
||
|
const idClipModel* model = collection[ i ];
|
||
|
|
||
|
bool isDead = false;
|
||
|
if ( model->GetEntity() == NULL ) {
|
||
|
if ( model->GetCollisionModel() != NULL ) {
|
||
|
isDead = !model->GetCollisionModel()->IsWorld();
|
||
|
} else {
|
||
|
isDead = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( isDead ) {
|
||
|
// the entity has been removed between updating the collection & now
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( !model->GetAbsBounds().IntersectsBounds( traceBounds ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( !( model->GetContents() & contentMask ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
trace_t trace;
|
||
|
gameLocal.clip.RotationModel( CLIP_DEBUG_PARMS_PASSTHRU trace, start, rotation, mdl, trmAxis, contentMask, model, model->GetOrigin(), model->GetAxis() );
|
||
|
if ( trace.fraction < results.fraction ) {
|
||
|
results = trace;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( mdl != NULL ) {
|
||
|
results.c.selfId = mdl->GetId();
|
||
|
} else {
|
||
|
results.c.selfId = 0;
|
||
|
}
|
||
|
return ( results.fraction != 1.0f );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::Contacts
|
||
|
============
|
||
|
*/
|
||
|
int sdClipModelCollection::Contacts( CLIP_DEBUG_PARMS_DECLARATION contactInfo_t *contacts, const int maxContacts,
|
||
|
const idVec3 &start, const idVec3 *dir, const float depth,
|
||
|
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask ) const {
|
||
|
|
||
|
if ( !g_useTraceCollection.GetBool() ) {
|
||
|
return gameLocal.clip.Contacts( CLIP_DEBUG_PARMS_PASSTHRU contacts, maxContacts, start, dir, depth, mdl, trmAxis, contentMask, self );
|
||
|
}
|
||
|
|
||
|
idBounds traceBounds;
|
||
|
if ( mdl != NULL ) {
|
||
|
traceBounds = mdl->GetBounds();
|
||
|
traceBounds.RotateSelf( trmAxis );
|
||
|
} else {
|
||
|
traceBounds[ 0 ].Set( -CM_BOX_EPSILON, -CM_BOX_EPSILON, -CM_BOX_EPSILON );
|
||
|
traceBounds[ 1 ].Set( CM_BOX_EPSILON, CM_BOX_EPSILON, CM_BOX_EPSILON );
|
||
|
}
|
||
|
|
||
|
traceBounds.TranslateSelf( start );
|
||
|
traceBounds.ExpandSelf( idMath::Fabs( depth ) + CM_BOX_EPSILON );
|
||
|
|
||
|
int numContacts = 0;
|
||
|
for ( int i = 0; i < collection.Num(); i++ ) {
|
||
|
const idClipModel* model = collection[ i ];
|
||
|
|
||
|
bool isDead = false;
|
||
|
if ( model->GetEntity() == NULL ) {
|
||
|
if ( model->GetCollisionModel() != NULL ) {
|
||
|
isDead = !model->GetCollisionModel()->IsWorld();
|
||
|
} else {
|
||
|
isDead = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( isDead ) {
|
||
|
// the entity has been removed between updating the collection & now
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( !model->GetAbsBounds().IntersectsBounds( traceBounds ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( !( model->GetContents() & contentMask ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
contactInfo_t* contactStart = contacts + numContacts;
|
||
|
int numClipContacts = gameLocal.clip.ContactsModel( CLIP_DEBUG_PARMS_PASSTHRU contactStart, maxContacts - numContacts, start, dir, depth, mdl, trmAxis, contentMask, model, model->GetOrigin(), model->GetAxis() );
|
||
|
for ( int j = 0; j < numClipContacts; j++ ) {
|
||
|
contactStart[ j ].entityNum = ( model->GetCollisionModel()->IsWorld() ) ? ENTITYNUM_WORLD : model->GetEntity()->entityNumber;;
|
||
|
contactStart[ j ].id = model->GetId();
|
||
|
contactStart[ j ].selfId = 0;
|
||
|
}
|
||
|
|
||
|
numContacts += numClipContacts;
|
||
|
}
|
||
|
|
||
|
return numContacts;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdClipModelCollection::Contents
|
||
|
============
|
||
|
*/
|
||
|
int sdClipModelCollection::Contents( CLIP_DEBUG_PARMS_DECLARATION const idVec3 &start,
|
||
|
const idClipModel *mdl, const idMat3 &trmAxis, int contentMask ) const {
|
||
|
if ( !g_useTraceCollection.GetBool() ) {
|
||
|
return gameLocal.clip.Contents( CLIP_DEBUG_PARMS_PASSTHRU start, mdl, trmAxis, contentMask, self );
|
||
|
}
|
||
|
|
||
|
idBounds traceBounds;
|
||
|
if ( mdl != NULL ) {
|
||
|
traceBounds = mdl->GetBounds();
|
||
|
traceBounds.RotateSelf( trmAxis );
|
||
|
} else {
|
||
|
traceBounds[ 0 ].Set( -CM_BOX_EPSILON, -CM_BOX_EPSILON, -CM_BOX_EPSILON );
|
||
|
traceBounds[ 1 ].Set( CM_BOX_EPSILON, CM_BOX_EPSILON, CM_BOX_EPSILON );
|
||
|
}
|
||
|
|
||
|
traceBounds.TranslateSelf( start );
|
||
|
traceBounds.ExpandSelf( CM_BOX_EPSILON );
|
||
|
|
||
|
int contents = 0;
|
||
|
for ( int i = 0; i < collection.Num(); i++ ) {
|
||
|
const idClipModel* model = collection[ i ];
|
||
|
|
||
|
bool isDead = false;
|
||
|
if ( model->GetEntity() == NULL ) {
|
||
|
if ( model->GetCollisionModel() != NULL ) {
|
||
|
isDead = !model->GetCollisionModel()->IsWorld();
|
||
|
} else {
|
||
|
isDead = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( isDead ) {
|
||
|
// the entity has been removed between updating the collection & now
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( !model->GetAbsBounds().IntersectsBounds( traceBounds ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( !( model->GetContents() & contentMask ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
contents |= gameLocal.clip.ContentsModel( CLIP_DEBUG_PARMS_PASSTHRU start, mdl, trmAxis, contentMask, model, model->GetOrigin(), model->GetAxis() );
|
||
|
}
|
||
|
|
||
|
return contents;
|
||
|
}
|