etqw-sdk/source/game/physics/Physics_Base.cpp

1151 lines
26 KiB
C++
Raw Permalink Normal View History

2008-05-29 00:00:00 +00:00
// 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;
}