1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
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.
13
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.
18
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/>.
21
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.
23
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.
25
26 ===========================================================================
27 */
28
29 #include "sys/platform.h"
30 #include "physics/Force.h"
31 #include "Entity.h"
32
33 #include "physics/Physics_Base.h"
34
CLASS_DECLARATION(idPhysics,idPhysics_Base)35 CLASS_DECLARATION( idPhysics, idPhysics_Base )
36 END_CLASS
37
38 /*
39 ================
40 idPhysics_Base::idPhysics_Base
41 ================
42 */
43 idPhysics_Base::idPhysics_Base( void ) {
44 self = NULL;
45 clipMask = 0;
46 SetGravity( gameLocal.GetGravity() );
47 ClearContacts();
48 }
49
50 /*
51 ================
52 idPhysics_Base::~idPhysics_Base
53 ================
54 */
~idPhysics_Base(void)55 idPhysics_Base::~idPhysics_Base( void ) {
56 if ( self && self->GetPhysics() == this ) {
57 self->SetPhysics( NULL );
58 }
59 idForce::DeletePhysics( this );
60 ClearContacts();
61 }
62
63 /*
64 ================
65 idPhysics_Base::Save
66 ================
67 */
Save(idSaveGame * savefile) const68 void idPhysics_Base::Save( idSaveGame *savefile ) const {
69 int i;
70
71 savefile->WriteObject( self );
72 savefile->WriteInt( clipMask );
73 savefile->WriteVec3( gravityVector );
74 savefile->WriteVec3( gravityNormal );
75
76 savefile->WriteInt( contacts.Num() );
77 for ( i = 0; i < contacts.Num(); i++ ) {
78 savefile->WriteContactInfo( contacts[i] );
79 }
80
81 savefile->WriteInt( contactEntities.Num() );
82 for ( i = 0; i < contactEntities.Num(); i++ ) {
83 contactEntities[i].Save( savefile );
84 }
85 }
86
87 /*
88 ================
89 idPhysics_Base::Restore
90 ================
91 */
Restore(idRestoreGame * savefile)92 void idPhysics_Base::Restore( idRestoreGame *savefile ) {
93 int i, num;
94
95 savefile->ReadObject( reinterpret_cast<idClass *&>( self ) );
96 savefile->ReadInt( clipMask );
97 savefile->ReadVec3( gravityVector );
98 savefile->ReadVec3( gravityNormal );
99
100 savefile->ReadInt( num );
101 contacts.SetNum( num );
102 for ( i = 0; i < contacts.Num(); i++ ) {
103 savefile->ReadContactInfo( contacts[i] );
104 }
105
106 savefile->ReadInt( num );
107 contactEntities.SetNum( num );
108 for ( i = 0; i < contactEntities.Num(); i++ ) {
109 contactEntities[i].Restore( savefile );
110 }
111 }
112
113 /*
114 ================
115 idPhysics_Base::SetSelf
116 ================
117 */
SetSelf(idEntity * e)118 void idPhysics_Base::SetSelf( idEntity *e ) {
119 assert( e );
120 self = e;
121 }
122
123 /*
124 ================
125 idPhysics_Base::SetClipModel
126 ================
127 */
SetClipModel(idClipModel * model,float density,int id,bool freeOld)128 void idPhysics_Base::SetClipModel( idClipModel *model, float density, int id, bool freeOld ) {
129 }
130
131 /*
132 ================
133 idPhysics_Base::GetClipModel
134 ================
135 */
GetClipModel(int id) const136 idClipModel *idPhysics_Base::GetClipModel( int id ) const {
137 return NULL;
138 }
139
140 /*
141 ================
142 idPhysics_Base::GetNumClipModels
143 ================
144 */
GetNumClipModels(void) const145 int idPhysics_Base::GetNumClipModels( void ) const {
146 return 0;
147 }
148
149 /*
150 ================
151 idPhysics_Base::SetMass
152 ================
153 */
SetMass(float mass,int id)154 void idPhysics_Base::SetMass( float mass, int id ) {
155 }
156
157 /*
158 ================
159 idPhysics_Base::GetMass
160 ================
161 */
GetMass(int id) const162 float idPhysics_Base::GetMass( int id ) const {
163 return 0.0f;
164 }
165
166 /*
167 ================
168 idPhysics_Base::SetContents
169 ================
170 */
SetContents(int contents,int id)171 void idPhysics_Base::SetContents( int contents, int id ) {
172 }
173
174 /*
175 ================
176 idPhysics_Base::SetClipMask
177 ================
178 */
GetContents(int id) const179 int idPhysics_Base::GetContents( int id ) const {
180 return 0;
181 }
182
183 /*
184 ================
185 idPhysics_Base::SetClipMask
186 ================
187 */
SetClipMask(int mask,int id)188 void idPhysics_Base::SetClipMask( int mask, int id ) {
189 clipMask = mask;
190 }
191
192 /*
193 ================
194 idPhysics_Base::GetClipMask
195 ================
196 */
GetClipMask(int id) const197 int idPhysics_Base::GetClipMask( int id ) const {
198 return clipMask;
199 }
200
201 /*
202 ================
203 idPhysics_Base::GetBounds
204 ================
205 */
GetBounds(int id) const206 const idBounds &idPhysics_Base::GetBounds( int id ) const {
207 return bounds_zero;
208 }
209
210 /*
211 ================
212 idPhysics_Base::GetAbsBounds
213 ================
214 */
GetAbsBounds(int id) const215 const idBounds &idPhysics_Base::GetAbsBounds( int id ) const {
216 return bounds_zero;
217 }
218
219 /*
220 ================
221 idPhysics_Base::Evaluate
222 ================
223 */
Evaluate(int timeStepMSec,int endTimeMSec)224 bool idPhysics_Base::Evaluate( int timeStepMSec, int endTimeMSec ) {
225 return false;
226 }
227
228 /*
229 ================
230 idPhysics_Base::UpdateTime
231 ================
232 */
UpdateTime(int endTimeMSec)233 void idPhysics_Base::UpdateTime( int endTimeMSec ) {
234 }
235
236 /*
237 ================
238 idPhysics_Base::GetTime
239 ================
240 */
GetTime(void) const241 int idPhysics_Base::GetTime( void ) const {
242 return 0;
243 }
244
245 /*
246 ================
247 idPhysics_Base::GetImpactInfo
248 ================
249 */
GetImpactInfo(const int id,const idVec3 & point,impactInfo_t * info) const250 void idPhysics_Base::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
251 memset( info, 0, sizeof( *info ) );
252 }
253
254 /*
255 ================
256 idPhysics_Base::ApplyImpulse
257 ================
258 */
ApplyImpulse(const int id,const idVec3 & point,const idVec3 & impulse)259 void idPhysics_Base::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
260 }
261
262 /*
263 ================
264 idPhysics_Base::AddForce
265 ================
266 */
AddForce(const int id,const idVec3 & point,const idVec3 & force)267 void idPhysics_Base::AddForce( const int id, const idVec3 &point, const idVec3 &force ) {
268 }
269
270 /*
271 ================
272 idPhysics_Base::Activate
273 ================
274 */
Activate(void)275 void idPhysics_Base::Activate( void ) {
276 }
277
278 /*
279 ================
280 idPhysics_Base::PutToRest
281 ================
282 */
PutToRest(void)283 void idPhysics_Base::PutToRest( void ) {
284 }
285
286 /*
287 ================
288 idPhysics_Base::IsAtRest
289 ================
290 */
IsAtRest(void) const291 bool idPhysics_Base::IsAtRest( void ) const {
292 return true;
293 }
294
295 /*
296 ================
297 idPhysics_Base::GetRestStartTime
298 ================
299 */
GetRestStartTime(void) const300 int idPhysics_Base::GetRestStartTime( void ) const {
301 return 0;
302 }
303
304 /*
305 ================
306 idPhysics_Base::IsPushable
307 ================
308 */
IsPushable(void) const309 bool idPhysics_Base::IsPushable( void ) const {
310 return true;
311 }
312
313 /*
314 ================
315 idPhysics_Base::SaveState
316 ================
317 */
SaveState(void)318 void idPhysics_Base::SaveState( void ) {
319 }
320
321 /*
322 ================
323 idPhysics_Base::RestoreState
324 ================
325 */
RestoreState(void)326 void idPhysics_Base::RestoreState( void ) {
327 }
328
329 /*
330 ================
331 idPhysics_Base::SetOrigin
332 ================
333 */
SetOrigin(const idVec3 & newOrigin,int id)334 void idPhysics_Base::SetOrigin( const idVec3 &newOrigin, int id ) {
335 }
336
337 /*
338 ================
339 idPhysics_Base::SetAxis
340 ================
341 */
SetAxis(const idMat3 & newAxis,int id)342 void idPhysics_Base::SetAxis( const idMat3 &newAxis, int id ) {
343 }
344
345 /*
346 ================
347 idPhysics_Base::Translate
348 ================
349 */
Translate(const idVec3 & translation,int id)350 void idPhysics_Base::Translate( const idVec3 &translation, int id ) {
351 }
352
353 /*
354 ================
355 idPhysics_Base::Rotate
356 ================
357 */
Rotate(const idRotation & rotation,int id)358 void idPhysics_Base::Rotate( const idRotation &rotation, int id ) {
359 }
360
361 /*
362 ================
363 idPhysics_Base::GetOrigin
364 ================
365 */
GetOrigin(int id) const366 const idVec3 &idPhysics_Base::GetOrigin( int id ) const {
367 return vec3_origin;
368 }
369
370 /*
371 ================
372 idPhysics_Base::GetAxis
373 ================
374 */
GetAxis(int id) const375 const idMat3 &idPhysics_Base::GetAxis( int id ) const {
376 return mat3_identity;
377 }
378
379 /*
380 ================
381 idPhysics_Base::SetLinearVelocity
382 ================
383 */
SetLinearVelocity(const idVec3 & newLinearVelocity,int id)384 void idPhysics_Base::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
385 }
386
387 /*
388 ================
389 idPhysics_Base::SetAngularVelocity
390 ================
391 */
SetAngularVelocity(const idVec3 & newAngularVelocity,int id)392 void idPhysics_Base::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
393 }
394
395 /*
396 ================
397 idPhysics_Base::GetLinearVelocity
398 ================
399 */
GetLinearVelocity(int id) const400 const idVec3 &idPhysics_Base::GetLinearVelocity( int id ) const {
401 return vec3_origin;
402 }
403
404 /*
405 ================
406 idPhysics_Base::GetAngularVelocity
407 ================
408 */
GetAngularVelocity(int id) const409 const idVec3 &idPhysics_Base::GetAngularVelocity( int id ) const {
410 return vec3_origin;
411 }
412
413 /*
414 ================
415 idPhysics_Base::SetGravity
416 ================
417 */
SetGravity(const idVec3 & newGravity)418 void idPhysics_Base::SetGravity( const idVec3 &newGravity ) {
419 gravityVector = newGravity;
420 gravityNormal = newGravity;
421 gravityNormal.Normalize();
422 }
423
424 /*
425 ================
426 idPhysics_Base::GetGravity
427 ================
428 */
GetGravity(void) const429 const idVec3 &idPhysics_Base::GetGravity( void ) const {
430 return gravityVector;
431 }
432
433 /*
434 ================
435 idPhysics_Base::GetGravityNormal
436 ================
437 */
GetGravityNormal(void) const438 const idVec3 &idPhysics_Base::GetGravityNormal( void ) const {
439 return gravityNormal;
440 }
441
442 /*
443 ================
444 idPhysics_Base::ClipTranslation
445 ================
446 */
ClipTranslation(trace_t & results,const idVec3 & translation,const idClipModel * model) const447 void idPhysics_Base::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
448 memset( &results, 0, sizeof( trace_t ) );
449 }
450
451 /*
452 ================
453 idPhysics_Base::ClipRotation
454 ================
455 */
ClipRotation(trace_t & results,const idRotation & rotation,const idClipModel * model) const456 void idPhysics_Base::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
457 memset( &results, 0, sizeof( trace_t ) );
458 }
459
460 /*
461 ================
462 idPhysics_Base::ClipContents
463 ================
464 */
ClipContents(const idClipModel * model) const465 int idPhysics_Base::ClipContents( const idClipModel *model ) const {
466 return 0;
467 }
468
469 /*
470 ================
471 idPhysics_Base::DisableClip
472 ================
473 */
DisableClip(void)474 void idPhysics_Base::DisableClip( void ) {
475 }
476
477 /*
478 ================
479 idPhysics_Base::EnableClip
480 ================
481 */
EnableClip(void)482 void idPhysics_Base::EnableClip( void ) {
483 }
484
485 /*
486 ================
487 idPhysics_Base::UnlinkClip
488 ================
489 */
UnlinkClip(void)490 void idPhysics_Base::UnlinkClip( void ) {
491 }
492
493 /*
494 ================
495 idPhysics_Base::LinkClip
496 ================
497 */
LinkClip(void)498 void idPhysics_Base::LinkClip( void ) {
499 }
500
501 /*
502 ================
503 idPhysics_Base::EvaluateContacts
504 ================
505 */
EvaluateContacts(void)506 bool idPhysics_Base::EvaluateContacts( void ) {
507 return false;
508 }
509
510 /*
511 ================
512 idPhysics_Base::GetNumContacts
513 ================
514 */
GetNumContacts(void) const515 int idPhysics_Base::GetNumContacts( void ) const {
516 return contacts.Num();
517 }
518
519 /*
520 ================
521 idPhysics_Base::GetContact
522 ================
523 */
GetContact(int num) const524 const contactInfo_t &idPhysics_Base::GetContact( int num ) const {
525 return contacts[num];
526 }
527
528 /*
529 ================
530 idPhysics_Base::ClearContacts
531 ================
532 */
ClearContacts(void)533 void idPhysics_Base::ClearContacts( void ) {
534 int i;
535 idEntity *ent;
536
537 for ( i = 0; i < contacts.Num(); i++ ) {
538 ent = gameLocal.entities[ contacts[i].entityNum ];
539 if ( ent ) {
540 ent->RemoveContactEntity( self );
541 }
542 }
543 contacts.SetNum( 0, false );
544 }
545
546 /*
547 ================
548 idPhysics_Base::AddContactEntity
549 ================
550 */
AddContactEntity(idEntity * e)551 void idPhysics_Base::AddContactEntity( idEntity *e ) {
552 int i;
553 idEntity *ent;
554 bool found = false;
555
556 for ( i = 0; i < contactEntities.Num(); i++ ) {
557 ent = contactEntities[i].GetEntity();
558 if ( ent == NULL ) {
559 contactEntities.RemoveIndex( i-- );
560 }
561 if ( ent == e ) {
562 found = true;
563 }
564 }
565 if ( !found ) {
566 contactEntities.Alloc() = e;
567 }
568 }
569
570 /*
571 ================
572 idPhysics_Base::RemoveContactEntity
573 ================
574 */
RemoveContactEntity(idEntity * e)575 void idPhysics_Base::RemoveContactEntity( idEntity *e ) {
576 int i;
577 idEntity *ent;
578
579 for ( i = 0; i < contactEntities.Num(); i++ ) {
580 ent = contactEntities[i].GetEntity();
581 if ( !ent ) {
582 contactEntities.RemoveIndex( i-- );
583 continue;
584 }
585 if ( ent == e ) {
586 contactEntities.RemoveIndex( i-- );
587 return;
588 }
589 }
590 }
591
592 /*
593 ================
594 idPhysics_Base::HasGroundContacts
595 ================
596 */
HasGroundContacts(void) const597 bool idPhysics_Base::HasGroundContacts( void ) const {
598 int i;
599
600 for ( i = 0; i < contacts.Num(); i++ ) {
601 if ( contacts[i].normal * -gravityNormal > 0.0f ) {
602 return true;
603 }
604 }
605 return false;
606 }
607
608 /*
609 ================
610 idPhysics_Base::IsGroundEntity
611 ================
612 */
IsGroundEntity(int entityNum) const613 bool idPhysics_Base::IsGroundEntity( int entityNum ) const {
614 int i;
615
616 for ( i = 0; i < contacts.Num(); i++ ) {
617 if ( contacts[i].entityNum == entityNum && ( contacts[i].normal * -gravityNormal > 0.0f ) ) {
618 return true;
619 }
620 }
621 return false;
622 }
623
624 /*
625 ================
626 idPhysics_Base::IsGroundClipModel
627 ================
628 */
IsGroundClipModel(int entityNum,int id) const629 bool idPhysics_Base::IsGroundClipModel( int entityNum, int id ) const {
630 int i;
631
632 for ( i = 0; i < contacts.Num(); i++ ) {
633 if ( contacts[i].entityNum == entityNum && contacts[i].id == id && ( contacts[i].normal * -gravityNormal > 0.0f ) ) {
634 return true;
635 }
636 }
637 return false;
638 }
639
640 /*
641 ================
642 idPhysics_Base::SetPushed
643 ================
644 */
SetPushed(int deltaTime)645 void idPhysics_Base::SetPushed( int deltaTime ) {
646 }
647
648 /*
649 ================
650 idPhysics_Base::GetPushedLinearVelocity
651 ================
652 */
GetPushedLinearVelocity(const int id) const653 const idVec3 &idPhysics_Base::GetPushedLinearVelocity( const int id ) const {
654 return vec3_origin;
655 }
656
657 /*
658 ================
659 idPhysics_Base::GetPushedAngularVelocity
660 ================
661 */
GetPushedAngularVelocity(const int id) const662 const idVec3 &idPhysics_Base::GetPushedAngularVelocity( const int id ) const {
663 return vec3_origin;
664 }
665
666 /*
667 ================
668 idPhysics_Base::SetMaster
669 ================
670 */
SetMaster(idEntity * master,const bool orientated)671 void idPhysics_Base::SetMaster( idEntity *master, const bool orientated ) {
672 }
673
674 /*
675 ================
676 idPhysics_Base::GetBlockingInfo
677 ================
678 */
GetBlockingInfo(void) const679 const trace_t *idPhysics_Base::GetBlockingInfo( void ) const {
680 return NULL;
681 }
682
683 /*
684 ================
685 idPhysics_Base::GetBlockingEntity
686 ================
687 */
GetBlockingEntity(void) const688 idEntity *idPhysics_Base::GetBlockingEntity( void ) const {
689 return NULL;
690 }
691
692 /*
693 ================
694 idPhysics_Base::GetLinearEndTime
695 ================
696 */
GetLinearEndTime(void) const697 int idPhysics_Base::GetLinearEndTime( void ) const {
698 return 0;
699 }
700
701 /*
702 ================
703 idPhysics_Base::GetAngularEndTime
704 ================
705 */
GetAngularEndTime(void) const706 int idPhysics_Base::GetAngularEndTime( void ) const {
707 return 0;
708 }
709
710 /*
711 ================
712 idPhysics_Base::AddGroundContacts
713 ================
714 */
AddGroundContacts(const idClipModel * clipModel)715 void idPhysics_Base::AddGroundContacts( const idClipModel *clipModel ) {
716 idVec6 dir;
717 int index, num;
718
719 index = contacts.Num();
720 contacts.SetNum( index + 10, false );
721
722 dir.SubVec3(0) = gravityNormal;
723 dir.SubVec3(1) = vec3_origin;
724 num = gameLocal.clip.Contacts( &contacts[index], 10, clipModel->GetOrigin(),
725 dir, CONTACT_EPSILON, clipModel, clipModel->GetAxis(), clipMask, self );
726 contacts.SetNum( index + num, false );
727 }
728
729 /*
730 ================
731 idPhysics_Base::AddContactEntitiesForContacts
732 ================
733 */
AddContactEntitiesForContacts(void)734 void idPhysics_Base::AddContactEntitiesForContacts( void ) {
735 int i;
736 idEntity *ent;
737
738 for ( i = 0; i < contacts.Num(); i++ ) {
739 ent = gameLocal.entities[ contacts[i].entityNum ];
740 if ( ent && ent != self ) {
741 ent->AddContactEntity( self );
742 }
743 }
744 }
745
746 /*
747 ================
748 idPhysics_Base::ActivateContactEntities
749 ================
750 */
ActivateContactEntities(void)751 void idPhysics_Base::ActivateContactEntities( void ) {
752 int i;
753 idEntity *ent;
754
755 for ( i = 0; i < contactEntities.Num(); i++ ) {
756 ent = contactEntities[i].GetEntity();
757 if ( ent ) {
758 ent->ActivatePhysics( self );
759 } else {
760 contactEntities.RemoveIndex( i-- );
761 }
762 }
763 }
764
765 /*
766 ================
767 idPhysics_Base::IsOutsideWorld
768 ================
769 */
IsOutsideWorld(void) const770 bool idPhysics_Base::IsOutsideWorld( void ) const {
771 if ( !gameLocal.clip.GetWorldBounds().Expand( 128.0f ).IntersectsBounds( GetAbsBounds() ) ) {
772 return true;
773 }
774 return false;
775 }
776
777 /*
778 ================
779 idPhysics_Base::DrawVelocity
780 ================
781 */
DrawVelocity(int id,float linearScale,float angularScale) const782 void idPhysics_Base::DrawVelocity( int id, float linearScale, float angularScale ) const {
783 idVec3 dir, org, vec, start, end;
784 idMat3 axis;
785 float length, a;
786
787 dir = GetLinearVelocity( id );
788 dir *= linearScale;
789 if ( dir.LengthSqr() > Square( 0.1f ) ) {
790 dir.Truncate( 10.0f );
791 org = GetOrigin( id );
792 gameRenderWorld->DebugArrow( colorRed, org, org + dir, 1 );
793 }
794
795 dir = GetAngularVelocity( id );
796 length = dir.Normalize();
797 length *= angularScale;
798 if ( length > 0.1f ) {
799 if ( length < 60.0f ) {
800 length = 60.0f;
801 }
802 else if ( length > 360.0f ) {
803 length = 360.0f;
804 }
805 axis = GetAxis( id );
806 vec = axis[2];
807 if ( idMath::Fabs( dir * vec ) > 0.99f ) {
808 vec = axis[0];
809 }
810 vec -= vec * dir * vec;
811 vec.Normalize();
812 vec *= 4.0f;
813 start = org + vec;
814 for ( a = 20.0f; a < length; a += 20.0f ) {
815 end = org + idRotation( vec3_origin, dir, -a ).ToMat3() * vec;
816 gameRenderWorld->DebugLine( colorBlue, start, end, 1 );
817 start = end;
818 }
819 end = org + idRotation( vec3_origin, dir, -length ).ToMat3() * vec;
820 gameRenderWorld->DebugArrow( colorBlue, start, end, 1 );
821 }
822 }
823
824 /*
825 ================
826 idPhysics_Base::WriteToSnapshot
827 ================
828 */
WriteToSnapshot(idBitMsgDelta & msg) const829 void idPhysics_Base::WriteToSnapshot( idBitMsgDelta &msg ) const {
830 }
831
832 /*
833 ================
834 idPhysics_Base::ReadFromSnapshot
835 ================
836 */
ReadFromSnapshot(const idBitMsgDelta & msg)837 void idPhysics_Base::ReadFromSnapshot( const idBitMsgDelta &msg ) {
838 }
839