2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
32 #include "../Game_local.h"
34 CLASS_DECLARATION( idPhysics, idPhysics_Base )
39 idPhysics_Base::idPhysics_Base
42 idPhysics_Base::idPhysics_Base( void ) {
45 SetGravity( gameLocal.GetGravity() );
51 idPhysics_Base::~idPhysics_Base
54 idPhysics_Base::~idPhysics_Base( void ) {
55 if ( self && self->GetPhysics() == this ) {
56 self->SetPhysics( NULL );
58 idForce::DeletePhysics( this );
67 void idPhysics_Base::Save( idSaveGame *savefile ) const {
70 savefile->WriteObject( self );
71 savefile->WriteInt( clipMask );
72 savefile->WriteVec3( gravityVector );
73 savefile->WriteVec3( gravityNormal );
75 savefile->WriteInt( contacts.Num() );
76 for ( i = 0; i < contacts.Num(); i++ ) {
77 savefile->WriteContactInfo( contacts[i] );
80 savefile->WriteInt( contactEntities.Num() );
81 for ( i = 0; i < contactEntities.Num(); i++ ) {
82 contactEntities[i].Save( savefile );
88 idPhysics_Base::Restore
91 void idPhysics_Base::Restore( idRestoreGame *savefile ) {
94 savefile->ReadObject( reinterpret_cast<idClass *&>( self ) );
95 savefile->ReadInt( clipMask );
96 savefile->ReadVec3( gravityVector );
97 savefile->ReadVec3( gravityNormal );
99 savefile->ReadInt( num );
100 contacts.SetNum( num );
101 for ( i = 0; i < contacts.Num(); i++ ) {
102 savefile->ReadContactInfo( contacts[i] );
105 savefile->ReadInt( num );
106 contactEntities.SetNum( num );
107 for ( i = 0; i < contactEntities.Num(); i++ ) {
108 contactEntities[i].Restore( savefile );
114 idPhysics_Base::SetSelf
117 void idPhysics_Base::SetSelf( idEntity *e ) {
124 idPhysics_Base::SetClipModel
127 void idPhysics_Base::SetClipModel( idClipModel *model, float density, int id, bool freeOld ) {
132 idPhysics_Base::GetClipModel
135 idClipModel *idPhysics_Base::GetClipModel( int id ) const {
141 idPhysics_Base::GetNumClipModels
144 int idPhysics_Base::GetNumClipModels( void ) const {
150 idPhysics_Base::SetMass
153 void idPhysics_Base::SetMass( float mass, int id ) {
158 idPhysics_Base::GetMass
161 float idPhysics_Base::GetMass( int id ) const {
167 idPhysics_Base::SetContents
170 void idPhysics_Base::SetContents( int contents, int id ) {
175 idPhysics_Base::SetClipMask
178 int idPhysics_Base::GetContents( int id ) const {
184 idPhysics_Base::SetClipMask
187 void idPhysics_Base::SetClipMask( int mask, int id ) {
193 idPhysics_Base::GetClipMask
196 int idPhysics_Base::GetClipMask( int id ) const {
202 idPhysics_Base::GetBounds
205 const idBounds &idPhysics_Base::GetBounds( int id ) const {
211 idPhysics_Base::GetAbsBounds
214 const idBounds &idPhysics_Base::GetAbsBounds( int id ) const {
220 idPhysics_Base::Evaluate
223 bool idPhysics_Base::Evaluate( int timeStepMSec, int endTimeMSec ) {
229 idPhysics_Base::UpdateTime
232 void idPhysics_Base::UpdateTime( int endTimeMSec ) {
237 idPhysics_Base::GetTime
240 int idPhysics_Base::GetTime( void ) const {
246 idPhysics_Base::GetImpactInfo
249 void idPhysics_Base::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
250 memset( info, 0, sizeof( *info ) );
255 idPhysics_Base::ApplyImpulse
258 void idPhysics_Base::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
263 idPhysics_Base::AddForce
266 void idPhysics_Base::AddForce( const int id, const idVec3 &point, const idVec3 &force ) {
271 idPhysics_Base::Activate
274 void idPhysics_Base::Activate( void ) {
279 idPhysics_Base::PutToRest
282 void idPhysics_Base::PutToRest( void ) {
287 idPhysics_Base::IsAtRest
290 bool idPhysics_Base::IsAtRest( void ) const {
296 idPhysics_Base::GetRestStartTime
299 int idPhysics_Base::GetRestStartTime( void ) const {
305 idPhysics_Base::IsPushable
308 bool idPhysics_Base::IsPushable( void ) const {
314 idPhysics_Base::SaveState
317 void idPhysics_Base::SaveState( void ) {
322 idPhysics_Base::RestoreState
325 void idPhysics_Base::RestoreState( void ) {
330 idPhysics_Base::SetOrigin
333 void idPhysics_Base::SetOrigin( const idVec3 &newOrigin, int id ) {
338 idPhysics_Base::SetAxis
341 void idPhysics_Base::SetAxis( const idMat3 &newAxis, int id ) {
346 idPhysics_Base::Translate
349 void idPhysics_Base::Translate( const idVec3 &translation, int id ) {
354 idPhysics_Base::Rotate
357 void idPhysics_Base::Rotate( const idRotation &rotation, int id ) {
362 idPhysics_Base::GetOrigin
365 const idVec3 &idPhysics_Base::GetOrigin( int id ) const {
371 idPhysics_Base::GetAxis
374 const idMat3 &idPhysics_Base::GetAxis( int id ) const {
375 return mat3_identity;
380 idPhysics_Base::SetLinearVelocity
383 void idPhysics_Base::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
388 idPhysics_Base::SetAngularVelocity
391 void idPhysics_Base::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
396 idPhysics_Base::GetLinearVelocity
399 const idVec3 &idPhysics_Base::GetLinearVelocity( int id ) const {
405 idPhysics_Base::GetAngularVelocity
408 const idVec3 &idPhysics_Base::GetAngularVelocity( int id ) const {
414 idPhysics_Base::SetGravity
417 void idPhysics_Base::SetGravity( const idVec3 &newGravity ) {
418 gravityVector = newGravity;
419 gravityNormal = newGravity;
420 gravityNormal.Normalize();
425 idPhysics_Base::GetGravity
428 const idVec3 &idPhysics_Base::GetGravity( void ) const {
429 return gravityVector;
434 idPhysics_Base::GetGravityNormal
437 const idVec3 &idPhysics_Base::GetGravityNormal( void ) const {
438 return gravityNormal;
443 idPhysics_Base::ClipTranslation
446 void idPhysics_Base::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
447 memset( &results, 0, sizeof( trace_t ) );
452 idPhysics_Base::ClipRotation
455 void idPhysics_Base::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
456 memset( &results, 0, sizeof( trace_t ) );
461 idPhysics_Base::ClipContents
464 int idPhysics_Base::ClipContents( const idClipModel *model ) const {
470 idPhysics_Base::DisableClip
473 void idPhysics_Base::DisableClip( void ) {
478 idPhysics_Base::EnableClip
481 void idPhysics_Base::EnableClip( void ) {
486 idPhysics_Base::UnlinkClip
489 void idPhysics_Base::UnlinkClip( void ) {
494 idPhysics_Base::LinkClip
497 void idPhysics_Base::LinkClip( void ) {
502 idPhysics_Base::EvaluateContacts
505 bool idPhysics_Base::EvaluateContacts( void ) {
511 idPhysics_Base::GetNumContacts
514 int idPhysics_Base::GetNumContacts( void ) const {
515 return contacts.Num();
520 idPhysics_Base::GetContact
523 const contactInfo_t &idPhysics_Base::GetContact( int num ) const {
524 return contacts[num];
529 idPhysics_Base::ClearContacts
532 void idPhysics_Base::ClearContacts( void ) {
536 for ( i = 0; i < contacts.Num(); i++ ) {
537 ent = gameLocal.entities[ contacts[i].entityNum ];
539 ent->RemoveContactEntity( self );
542 contacts.SetNum( 0, false );
547 idPhysics_Base::AddContactEntity
550 void idPhysics_Base::AddContactEntity( idEntity *e ) {
555 for ( i = 0; i < contactEntities.Num(); i++ ) {
556 ent = contactEntities[i].GetEntity();
558 contactEntities.RemoveIndex( i-- );
565 contactEntities.Alloc() = e;
571 idPhysics_Base::RemoveContactEntity
574 void idPhysics_Base::RemoveContactEntity( idEntity *e ) {
578 for ( i = 0; i < contactEntities.Num(); i++ ) {
579 ent = contactEntities[i].GetEntity();
581 contactEntities.RemoveIndex( i-- );
585 contactEntities.RemoveIndex( i-- );
593 idPhysics_Base::HasGroundContacts
596 bool idPhysics_Base::HasGroundContacts( void ) const {
599 for ( i = 0; i < contacts.Num(); i++ ) {
600 if ( contacts[i].normal * -gravityNormal > 0.0f ) {
609 idPhysics_Base::IsGroundEntity
612 bool idPhysics_Base::IsGroundEntity( int entityNum ) const {
615 for ( i = 0; i < contacts.Num(); i++ ) {
616 if ( contacts[i].entityNum == entityNum && ( contacts[i].normal * -gravityNormal > 0.0f ) ) {
625 idPhysics_Base::IsGroundClipModel
628 bool idPhysics_Base::IsGroundClipModel( int entityNum, int id ) const {
631 for ( i = 0; i < contacts.Num(); i++ ) {
632 if ( contacts[i].entityNum == entityNum && contacts[i].id == id && ( contacts[i].normal * -gravityNormal > 0.0f ) ) {
641 idPhysics_Base::SetPushed
644 void idPhysics_Base::SetPushed( int deltaTime ) {
649 idPhysics_Base::GetPushedLinearVelocity
652 const idVec3 &idPhysics_Base::GetPushedLinearVelocity( const int id ) const {
658 idPhysics_Base::GetPushedAngularVelocity
661 const idVec3 &idPhysics_Base::GetPushedAngularVelocity( const int id ) const {
667 idPhysics_Base::SetMaster
670 void idPhysics_Base::SetMaster( idEntity *master, const bool orientated ) {
675 idPhysics_Base::GetBlockingInfo
678 const trace_t *idPhysics_Base::GetBlockingInfo( void ) const {
684 idPhysics_Base::GetBlockingEntity
687 idEntity *idPhysics_Base::GetBlockingEntity( void ) const {
693 idPhysics_Base::GetLinearEndTime
696 int idPhysics_Base::GetLinearEndTime( void ) const {
702 idPhysics_Base::GetAngularEndTime
705 int idPhysics_Base::GetAngularEndTime( void ) const {
711 idPhysics_Base::AddGroundContacts
714 void idPhysics_Base::AddGroundContacts( const idClipModel *clipModel ) {
718 index = contacts.Num();
719 contacts.SetNum( index + 10, false );
721 dir.SubVec3(0) = gravityNormal;
722 dir.SubVec3(1) = vec3_origin;
723 num = gameLocal.clip.Contacts( &contacts[index], 10, clipModel->GetOrigin(),
724 dir, CONTACT_EPSILON, clipModel, clipModel->GetAxis(), clipMask, self );
725 contacts.SetNum( index + num, false );
730 idPhysics_Base::AddContactEntitiesForContacts
733 void idPhysics_Base::AddContactEntitiesForContacts( void ) {
737 for ( i = 0; i < contacts.Num(); i++ ) {
738 ent = gameLocal.entities[ contacts[i].entityNum ];
739 if ( ent && ent != self ) {
740 ent->AddContactEntity( self );
747 idPhysics_Base::ActivateContactEntities
750 void idPhysics_Base::ActivateContactEntities( void ) {
754 for ( i = 0; i < contactEntities.Num(); i++ ) {
755 ent = contactEntities[i].GetEntity();
757 ent->ActivatePhysics( self );
759 contactEntities.RemoveIndex( i-- );
766 idPhysics_Base::IsOutsideWorld
769 bool idPhysics_Base::IsOutsideWorld( void ) const {
770 if ( !gameLocal.clip.GetWorldBounds().Expand( 128.0f ).IntersectsBounds( GetAbsBounds() ) ) {
778 idPhysics_Base::DrawVelocity
781 void idPhysics_Base::DrawVelocity( int id, float linearScale, float angularScale ) const {
782 idVec3 dir, org, vec, start, end;
786 dir = GetLinearVelocity( id );
788 if ( dir.LengthSqr() > Square( 0.1f ) ) {
789 dir.Truncate( 10.0f );
790 org = GetOrigin( id );
791 gameRenderWorld->DebugArrow( colorRed, org, org + dir, 1 );
794 dir = GetAngularVelocity( id );
795 length = dir.Normalize();
796 length *= angularScale;
797 if ( length > 0.1f ) {
798 if ( length < 60.0f ) {
801 else if ( length > 360.0f ) {
804 axis = GetAxis( id );
806 if ( idMath::Fabs( dir * vec ) > 0.99f ) {
809 vec -= vec * dir * vec;
813 for ( a = 20.0f; a < length; a += 20.0f ) {
814 end = org + idRotation( vec3_origin, dir, -a ).ToMat3() * vec;
815 gameRenderWorld->DebugLine( colorBlue, start, end, 1 );
818 end = org + idRotation( vec3_origin, dir, -length ).ToMat3() * vec;
819 gameRenderWorld->DebugArrow( colorBlue, start, end, 1 );
825 idPhysics_Base::WriteToSnapshot
828 void idPhysics_Base::WriteToSnapshot( idBitMsgDelta &msg ) const {
833 idPhysics_Base::ReadFromSnapshot
836 void idPhysics_Base::ReadFromSnapshot( const idBitMsgDelta &msg ) {