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