]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/game/physics/Physics_Parametric.cpp
hello world
[icculus/iodoom3.git] / neo / game / physics / Physics_Parametric.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_Base, idPhysics_Parametric )
35 END_CLASS
36
37
38 /*
39 ================
40 idPhysics_Parametric::Activate
41 ================
42 */
43 void idPhysics_Parametric::Activate( void ) {
44         current.atRest = -1;
45         self->BecomeActive( TH_PHYSICS );
46 }
47
48 /*
49 ================
50 idPhysics_Parametric::TestIfAtRest
51 ================
52 */
53 bool idPhysics_Parametric::TestIfAtRest( void ) const {
54
55         if ( ( current.linearExtrapolation.GetExtrapolationType() & ~EXTRAPOLATION_NOSTOP ) == EXTRAPOLATION_NONE &&
56                         ( current.angularExtrapolation.GetExtrapolationType() & ~EXTRAPOLATION_NOSTOP ) == EXTRAPOLATION_NONE &&
57                                 current.linearInterpolation.GetDuration() == 0 &&
58                                         current.angularInterpolation.GetDuration() == 0 &&
59                                                 current.spline == NULL ) {
60                 return true;
61         }
62
63         if ( !current.linearExtrapolation.IsDone( current.time ) ) {
64                 return false;
65         }
66
67         if ( !current.angularExtrapolation.IsDone( current.time ) ) {
68                 return false;
69         }
70
71         if ( !current.linearInterpolation.IsDone( current.time ) ) {
72                 return false;
73         }
74
75         if ( !current.angularInterpolation.IsDone( current.time ) ) {
76                 return false;
77         }
78
79         if ( current.spline != NULL && !current.spline->IsDone( current.time ) ) {
80                 return false;
81         }
82
83         return true;
84 }
85
86 /*
87 ================
88 idPhysics_Parametric::Rest
89 ================
90 */
91 void idPhysics_Parametric::Rest( void ) {
92         current.atRest = gameLocal.time;
93         self->BecomeInactive( TH_PHYSICS );
94 }
95
96 /*
97 ================
98 idPhysics_Parametric::idPhysics_Parametric
99 ================
100 */
101 idPhysics_Parametric::idPhysics_Parametric( void ) {
102
103         current.time = gameLocal.time;
104         current.atRest = -1;
105         current.useSplineAngles = false;
106         current.origin.Zero();
107         current.angles.Zero();
108         current.axis.Identity();
109         current.localOrigin.Zero();
110         current.localAngles.Zero();
111         current.linearExtrapolation.Init( 0, 0, vec3_zero, vec3_zero, vec3_zero, EXTRAPOLATION_NONE );
112         current.angularExtrapolation.Init( 0, 0, ang_zero, ang_zero, ang_zero, EXTRAPOLATION_NONE );
113         current.linearInterpolation.Init( 0, 0, 0, 0, vec3_zero, vec3_zero );
114         current.angularInterpolation.Init( 0, 0, 0, 0, ang_zero, ang_zero );
115         current.spline = NULL;
116         current.splineInterpolate.Init( 0, 1, 1, 2, 0, 0 );
117
118         saved = current;
119
120         isPusher = false;
121         pushFlags = 0;
122         clipModel = NULL;
123         isBlocked = false;
124         memset( &pushResults, 0, sizeof( pushResults ) );
125
126         hasMaster = false;
127         isOrientated = false;
128 }
129
130 /*
131 ================
132 idPhysics_Parametric::~idPhysics_Parametric
133 ================
134 */
135 idPhysics_Parametric::~idPhysics_Parametric( void ) {
136         if ( clipModel != NULL ) {
137                 delete clipModel;
138                 clipModel = NULL;
139         }
140         if ( current.spline != NULL ) {
141                 delete current.spline;
142                 current.spline = NULL;
143         }
144 }
145
146 /*
147 ================
148 idPhysics_Parametric_SavePState
149 ================
150 */
151 void idPhysics_Parametric_SavePState( idSaveGame *savefile, const parametricPState_t &state ) {
152         savefile->WriteInt( state.time );
153         savefile->WriteInt( state.atRest );
154         savefile->WriteBool( state.useSplineAngles );
155         savefile->WriteVec3( state.origin );
156         savefile->WriteAngles( state.angles );
157         savefile->WriteMat3( state.axis );
158         savefile->WriteVec3( state.localOrigin );
159         savefile->WriteAngles( state.localAngles );
160
161         savefile->WriteInt( (int)state.linearExtrapolation.GetExtrapolationType() );
162         savefile->WriteFloat( state.linearExtrapolation.GetStartTime() );
163         savefile->WriteFloat( state.linearExtrapolation.GetDuration() );
164         savefile->WriteVec3( state.linearExtrapolation.GetStartValue() );
165         savefile->WriteVec3( state.linearExtrapolation.GetBaseSpeed() );
166         savefile->WriteVec3( state.linearExtrapolation.GetSpeed() );
167
168         savefile->WriteInt( (int)state.angularExtrapolation.GetExtrapolationType() );
169         savefile->WriteFloat( state.angularExtrapolation.GetStartTime() );
170         savefile->WriteFloat( state.angularExtrapolation.GetDuration() );
171         savefile->WriteAngles( state.angularExtrapolation.GetStartValue() );
172         savefile->WriteAngles( state.angularExtrapolation.GetBaseSpeed() );
173         savefile->WriteAngles( state.angularExtrapolation.GetSpeed() );
174
175         savefile->WriteFloat( state.linearInterpolation.GetStartTime() );
176         savefile->WriteFloat( state.linearInterpolation.GetAcceleration() );
177         savefile->WriteFloat( state.linearInterpolation.GetDeceleration() );
178         savefile->WriteFloat( state.linearInterpolation.GetDuration() );
179         savefile->WriteVec3( state.linearInterpolation.GetStartValue() );
180         savefile->WriteVec3( state.linearInterpolation.GetEndValue() );
181
182         savefile->WriteFloat( state.angularInterpolation.GetStartTime() );
183         savefile->WriteFloat( state.angularInterpolation.GetAcceleration() );
184         savefile->WriteFloat( state.angularInterpolation.GetDeceleration() );
185         savefile->WriteFloat( state.angularInterpolation.GetDuration() );
186         savefile->WriteAngles( state.angularInterpolation.GetStartValue() );
187         savefile->WriteAngles( state.angularInterpolation.GetEndValue() );
188
189         // spline is handled by owner
190
191         savefile->WriteFloat( state.splineInterpolate.GetStartTime() );
192         savefile->WriteFloat( state.splineInterpolate.GetAcceleration() );
193         savefile->WriteFloat( state.splineInterpolate.GetDuration() );
194         savefile->WriteFloat( state.splineInterpolate.GetDeceleration() );
195         savefile->WriteFloat( state.splineInterpolate.GetStartValue() );
196         savefile->WriteFloat( state.splineInterpolate.GetEndValue() );
197 }
198
199 /*
200 ================
201 idPhysics_Parametric_RestorePState
202 ================
203 */
204 void idPhysics_Parametric_RestorePState( idRestoreGame *savefile, parametricPState_t &state ) {
205         extrapolation_t etype;
206         float startTime, duration, accelTime, decelTime, startValue, endValue;
207         idVec3 linearStartValue, linearBaseSpeed, linearSpeed, startPos, endPos;
208         idAngles angularStartValue, angularBaseSpeed, angularSpeed, startAng, endAng;
209
210         savefile->ReadInt( state.time );
211         savefile->ReadInt( state.atRest );
212         savefile->ReadBool( state.useSplineAngles );
213         savefile->ReadVec3( state.origin );
214         savefile->ReadAngles( state.angles );
215         savefile->ReadMat3( state.axis );
216         savefile->ReadVec3( state.localOrigin );
217         savefile->ReadAngles( state.localAngles );
218
219         savefile->ReadInt( (int &)etype );
220         savefile->ReadFloat( startTime );
221         savefile->ReadFloat( duration );
222         savefile->ReadVec3( linearStartValue );
223         savefile->ReadVec3( linearBaseSpeed );
224         savefile->ReadVec3( linearSpeed );
225
226         state.linearExtrapolation.Init( startTime, duration, linearStartValue, linearBaseSpeed, linearSpeed, etype );
227
228         savefile->ReadInt( (int &)etype );
229         savefile->ReadFloat( startTime );
230         savefile->ReadFloat( duration );
231         savefile->ReadAngles( angularStartValue );
232         savefile->ReadAngles( angularBaseSpeed );
233         savefile->ReadAngles( angularSpeed );
234
235         state.angularExtrapolation.Init( startTime, duration, angularStartValue, angularBaseSpeed, angularSpeed, etype );
236
237         savefile->ReadFloat( startTime );
238         savefile->ReadFloat( accelTime );
239         savefile->ReadFloat( decelTime );
240         savefile->ReadFloat( duration );
241         savefile->ReadVec3( startPos );
242         savefile->ReadVec3( endPos );
243
244         state.linearInterpolation.Init( startTime, accelTime, decelTime, duration, startPos, endPos );
245
246         savefile->ReadFloat( startTime );
247         savefile->ReadFloat( accelTime );
248         savefile->ReadFloat( decelTime );
249         savefile->ReadFloat( duration );
250         savefile->ReadAngles( startAng );
251         savefile->ReadAngles( endAng );
252
253         state.angularInterpolation.Init( startTime, accelTime, decelTime, duration, startAng, endAng );
254
255         // spline is handled by owner
256
257         savefile->ReadFloat( startTime );
258         savefile->ReadFloat( accelTime );
259         savefile->ReadFloat( duration );
260         savefile->ReadFloat( decelTime );
261         savefile->ReadFloat( startValue );
262         savefile->ReadFloat( endValue );
263
264         state.splineInterpolate.Init( startTime, accelTime, decelTime, duration, startValue, endValue );
265 }
266
267 /*
268 ================
269 idPhysics_Parametric::Save
270 ================
271 */
272 void idPhysics_Parametric::Save( idSaveGame *savefile ) const {
273
274         idPhysics_Parametric_SavePState( savefile, current );
275         idPhysics_Parametric_SavePState( savefile, saved );
276
277         savefile->WriteBool( isPusher );
278         savefile->WriteClipModel( clipModel );
279         savefile->WriteInt( pushFlags );
280
281         savefile->WriteTrace( pushResults );
282         savefile->WriteBool( isBlocked );
283
284         savefile->WriteBool( hasMaster );
285         savefile->WriteBool( isOrientated );
286 }
287
288 /*
289 ================
290 idPhysics_Parametric::Restore
291 ================
292 */
293 void idPhysics_Parametric::Restore( idRestoreGame *savefile ) {
294
295         idPhysics_Parametric_RestorePState( savefile, current );
296         idPhysics_Parametric_RestorePState( savefile, saved );
297
298         savefile->ReadBool( isPusher );
299         savefile->ReadClipModel( clipModel );
300         savefile->ReadInt( pushFlags );
301
302         savefile->ReadTrace( pushResults );
303         savefile->ReadBool( isBlocked );
304
305         savefile->ReadBool( hasMaster );
306         savefile->ReadBool( isOrientated );
307 }
308
309 /*
310 ================
311 idPhysics_Parametric::SetPusher
312 ================
313 */
314 void idPhysics_Parametric::SetPusher( int flags ) {
315         assert( clipModel );
316         isPusher = true;
317         pushFlags = flags;
318 }
319
320 /*
321 ================
322 idPhysics_Parametric::IsPusher
323 ================
324 */
325 bool idPhysics_Parametric::IsPusher( void ) const {
326         return isPusher;
327 }
328
329 /*
330 ================
331 idPhysics_Parametric::SetLinearExtrapolation
332 ================
333 */
334 void idPhysics_Parametric::SetLinearExtrapolation( extrapolation_t type, int time, int duration, const idVec3 &base, const idVec3 &speed, const idVec3 &baseSpeed ) {
335         current.time = gameLocal.time;
336         current.linearExtrapolation.Init( time, duration, base, baseSpeed, speed, type );
337         current.localOrigin = base;
338         Activate();
339 }
340
341 /*
342 ================
343 idPhysics_Parametric::SetAngularExtrapolation
344 ================
345 */
346 void idPhysics_Parametric::SetAngularExtrapolation( extrapolation_t type, int time, int duration, const idAngles &base, const idAngles &speed, const idAngles &baseSpeed ) {
347         current.time = gameLocal.time;
348         current.angularExtrapolation.Init( time, duration, base, baseSpeed, speed, type );
349         current.localAngles = base;
350         Activate();
351 }
352
353 /*
354 ================
355 idPhysics_Parametric::GetLinearExtrapolationType
356 ================
357 */
358 extrapolation_t idPhysics_Parametric::GetLinearExtrapolationType( void ) const {
359         return current.linearExtrapolation.GetExtrapolationType();
360 }
361
362 /*
363 ================
364 idPhysics_Parametric::GetAngularExtrapolationType
365 ================
366 */
367 extrapolation_t idPhysics_Parametric::GetAngularExtrapolationType( void ) const {
368         return current.angularExtrapolation.GetExtrapolationType();
369 }
370
371 /*
372 ================
373 idPhysics_Parametric::SetLinearInterpolation
374 ================
375 */
376 void idPhysics_Parametric::SetLinearInterpolation( int time, int accelTime, int decelTime, int duration, const idVec3 &startPos, const idVec3 &endPos ) {
377         current.time = gameLocal.time;
378         current.linearInterpolation.Init( time, accelTime, decelTime, duration, startPos, endPos );
379         current.localOrigin = startPos;
380         Activate();
381 }
382
383 /*
384 ================
385 idPhysics_Parametric::SetAngularInterpolation
386 ================
387 */
388 void idPhysics_Parametric::SetAngularInterpolation( int time, int accelTime, int decelTime, int duration, const idAngles &startAng, const idAngles &endAng ) {
389         current.time = gameLocal.time;
390         current.angularInterpolation.Init( time, accelTime, decelTime, duration, startAng, endAng );
391         current.localAngles = startAng;
392         Activate();
393 }
394
395 /*
396 ================
397 idPhysics_Parametric::SetSpline
398 ================
399 */
400 void idPhysics_Parametric::SetSpline( idCurve_Spline<idVec3> *spline, int accelTime, int decelTime, bool useSplineAngles ) {
401         if ( current.spline != NULL ) {
402                 delete current.spline;
403                 current.spline = NULL;
404         }
405         current.spline = spline;
406         if ( current.spline != NULL ) {
407                 float startTime = current.spline->GetTime( 0 );
408                 float endTime = current.spline->GetTime( current.spline->GetNumValues() - 1 );
409                 float length = current.spline->GetLengthForTime( endTime );
410                 current.splineInterpolate.Init( startTime, accelTime, decelTime, endTime - startTime, 0.0f, length );
411         }
412         current.useSplineAngles = useSplineAngles;
413         Activate();
414 }
415
416 /*
417 ================
418 idPhysics_Parametric::GetSpline
419 ================
420 */
421 idCurve_Spline<idVec3> *idPhysics_Parametric::GetSpline( void ) const {
422         return current.spline;
423 }
424
425 /*
426 ================
427 idPhysics_Parametric::GetSplineAcceleration
428 ================
429 */
430 int idPhysics_Parametric::GetSplineAcceleration( void ) const {
431         return current.splineInterpolate.GetAcceleration();
432 }
433
434 /*
435 ================
436 idPhysics_Parametric::GetSplineDeceleration
437 ================
438 */
439 int idPhysics_Parametric::GetSplineDeceleration( void ) const {
440         return current.splineInterpolate.GetDeceleration();
441 }
442
443 /*
444 ================
445 idPhysics_Parametric::UsingSplineAngles
446 ================
447 */
448 bool idPhysics_Parametric::UsingSplineAngles( void ) const {
449         return current.useSplineAngles;
450 }
451
452 /*
453 ================
454 idPhysics_Parametric::GetLocalOrigin
455 ================
456 */
457 void idPhysics_Parametric::GetLocalOrigin( idVec3 &curOrigin ) const {
458         curOrigin = current.localOrigin;
459 }
460
461 /*
462 ================
463 idPhysics_Parametric::GetLocalAngles
464 ================
465 */
466 void idPhysics_Parametric::GetLocalAngles( idAngles &curAngles ) const {
467         curAngles = current.localAngles;
468 }
469
470 /*
471 ================
472 idPhysics_Parametric::SetClipModel
473 ================
474 */
475 void idPhysics_Parametric::SetClipModel( idClipModel *model, float density, int id, bool freeOld ) {
476
477         assert( self );
478         assert( model );
479
480         if ( clipModel && clipModel != model && freeOld ) {
481                 delete clipModel;
482         }
483         clipModel = model;
484         clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
485 }
486
487 /*
488 ================
489 idPhysics_Parametric::GetClipModel
490 ================
491 */
492 idClipModel *idPhysics_Parametric::GetClipModel( int id ) const {
493         return clipModel;
494 }
495
496 /*
497 ================
498 idPhysics_Parametric::GetNumClipModels
499 ================
500 */
501 int idPhysics_Parametric::GetNumClipModels( void ) const {
502         return ( clipModel != NULL );
503 }
504
505 /*
506 ================
507 idPhysics_Parametric::SetMass
508 ================
509 */
510 void idPhysics_Parametric::SetMass( float mass, int id ) {
511 }
512
513 /*
514 ================
515 idPhysics_Parametric::GetMass
516 ================
517 */
518 float idPhysics_Parametric::GetMass( int id ) const {
519         return 0.0f;
520 }
521
522 /*
523 ================
524 idPhysics_Parametric::SetClipMask
525 ================
526 */
527 void idPhysics_Parametric::SetContents( int contents, int id ) {
528         if ( clipModel ) {
529                 clipModel->SetContents( contents );
530         }
531 }
532
533 /*
534 ================
535 idPhysics_Parametric::SetClipMask
536 ================
537 */
538 int idPhysics_Parametric::GetContents( int id ) const {
539         if ( clipModel ) {
540                 return clipModel->GetContents();
541         }
542         return 0;
543 }
544
545 /*
546 ================
547 idPhysics_Parametric::GetBounds
548 ================
549 */
550 const idBounds &idPhysics_Parametric::GetBounds( int id ) const {
551         if ( clipModel ) {
552                 return clipModel->GetBounds();
553         }
554         return idPhysics_Base::GetBounds();
555 }
556
557 /*
558 ================
559 idPhysics_Parametric::GetAbsBounds
560 ================
561 */
562 const idBounds &idPhysics_Parametric::GetAbsBounds( int id ) const {
563         if ( clipModel ) {
564                 return clipModel->GetAbsBounds();
565         }
566         return idPhysics_Base::GetAbsBounds();
567 }
568
569 /*
570 ================
571 idPhysics_Parametric::Evaluate
572 ================
573 */
574 bool idPhysics_Parametric::Evaluate( int timeStepMSec, int endTimeMSec ) {
575         idVec3 oldLocalOrigin, oldOrigin, masterOrigin;
576         idAngles oldLocalAngles, oldAngles;
577         idMat3 oldAxis, masterAxis;
578
579         isBlocked = false;
580         oldLocalOrigin = current.localOrigin;
581         oldOrigin = current.origin;
582         oldLocalAngles = current.localAngles;
583         oldAngles = current.angles;
584         oldAxis = current.axis;
585
586         current.localOrigin.Zero();
587         current.localAngles.Zero();
588
589         if ( current.spline != NULL ) {
590                 float length = current.splineInterpolate.GetCurrentValue( endTimeMSec );
591                 float t = current.spline->GetTimeForLength( length, 0.01f );
592                 current.localOrigin = current.spline->GetCurrentValue( t );
593                 if ( current.useSplineAngles ) {
594                         current.localAngles = current.spline->GetCurrentFirstDerivative( t ).ToAngles();
595                 }
596         } else if ( current.linearInterpolation.GetDuration() != 0 ) {
597                 current.localOrigin += current.linearInterpolation.GetCurrentValue( endTimeMSec );
598         } else {
599                 current.localOrigin += current.linearExtrapolation.GetCurrentValue( endTimeMSec );
600         }
601
602         if ( current.angularInterpolation.GetDuration() != 0 ) {
603                 current.localAngles += current.angularInterpolation.GetCurrentValue( endTimeMSec );
604         } else {
605                 current.localAngles += current.angularExtrapolation.GetCurrentValue( endTimeMSec );
606         }
607
608         current.localAngles.Normalize360();
609         current.origin = current.localOrigin;
610         current.angles = current.localAngles;
611         current.axis = current.localAngles.ToMat3();
612
613         if ( hasMaster ) {
614                 self->GetMasterPosition( masterOrigin, masterAxis );
615                 if ( masterAxis.IsRotated() ) {
616                         current.origin = current.origin * masterAxis + masterOrigin;
617                         if ( isOrientated ) {
618                                 current.axis *= masterAxis;
619                                 current.angles = current.axis.ToAngles();
620                         }
621                 }
622                 else {
623                         current.origin += masterOrigin;
624                 }
625         }
626
627         if ( isPusher ) {
628
629                 gameLocal.push.ClipPush( pushResults, self, pushFlags, oldOrigin, oldAxis, current.origin, current.axis );
630                 if ( pushResults.fraction < 1.0f ) {
631                         clipModel->Link( gameLocal.clip, self, 0, oldOrigin, oldAxis );
632                         current.localOrigin = oldLocalOrigin;
633                         current.origin = oldOrigin;
634                         current.localAngles = oldLocalAngles;
635                         current.angles = oldAngles;
636                         current.axis = oldAxis;
637                         isBlocked = true;
638                         return false;
639                 }
640
641                 current.angles = current.axis.ToAngles();
642         }
643
644         if ( clipModel ) {
645                 clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
646         }
647
648         current.time = endTimeMSec;
649
650         if ( TestIfAtRest() ) {
651                 Rest();
652         }
653
654         return ( current.origin != oldOrigin || current.axis != oldAxis );
655 }
656
657 /*
658 ================
659 idPhysics_Parametric::UpdateTime
660 ================
661 */
662 void idPhysics_Parametric::UpdateTime( int endTimeMSec ) {
663         int timeLeap = endTimeMSec - current.time;
664
665         current.time = endTimeMSec;
666         // move the trajectory start times to sync the trajectory with the current endTime
667         current.linearExtrapolation.SetStartTime( current.linearExtrapolation.GetStartTime() + timeLeap );
668         current.angularExtrapolation.SetStartTime( current.angularExtrapolation.GetStartTime() + timeLeap );
669         current.linearInterpolation.SetStartTime( current.linearInterpolation.GetStartTime() + timeLeap );
670         current.angularInterpolation.SetStartTime( current.angularInterpolation.GetStartTime() + timeLeap );
671         if ( current.spline != NULL ) {
672                 current.spline->ShiftTime( timeLeap );
673                 current.splineInterpolate.SetStartTime( current.splineInterpolate.GetStartTime() + timeLeap );
674         }
675 }
676
677 /*
678 ================
679 idPhysics_Parametric::GetTime
680 ================
681 */
682 int idPhysics_Parametric::GetTime( void ) const {
683         return current.time;
684 }
685
686 /*
687 ================
688 idPhysics_Parametric::IsAtRest
689 ================
690 */
691 bool idPhysics_Parametric::IsAtRest( void ) const {
692         return current.atRest >= 0;
693 }
694
695 /*
696 ================
697 idPhysics_Parametric::GetRestStartTime
698 ================
699 */
700 int idPhysics_Parametric::GetRestStartTime( void ) const {
701         return current.atRest;
702 }
703
704 /*
705 ================
706 idPhysics_Parametric::IsPushable
707 ================
708 */
709 bool idPhysics_Parametric::IsPushable( void ) const {
710         return false;
711 }
712
713 /*
714 ================
715 idPhysics_Parametric::SaveState
716 ================
717 */
718 void idPhysics_Parametric::SaveState( void ) {
719         saved = current;
720 }
721
722 /*
723 ================
724 idPhysics_Parametric::RestoreState
725 ================
726 */
727 void idPhysics_Parametric::RestoreState( void ) {
728
729         current = saved;
730
731         if ( clipModel ) {
732                 clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
733         }
734 }
735
736 /*
737 ================
738 idPhysics_Parametric::SetOrigin
739 ================
740 */
741 void idPhysics_Parametric::SetOrigin( const idVec3 &newOrigin, int id ) {
742         idVec3 masterOrigin;
743         idMat3 masterAxis;
744
745         current.linearExtrapolation.SetStartValue( newOrigin );
746         current.linearInterpolation.SetStartValue( newOrigin );
747
748         current.localOrigin = current.linearExtrapolation.GetCurrentValue( current.time );
749         if ( hasMaster ) {
750                 self->GetMasterPosition( masterOrigin, masterAxis );
751                 current.origin = masterOrigin + current.localOrigin * masterAxis;
752         }
753         else {
754                 current.origin = current.localOrigin;
755         }
756         if ( clipModel ) {
757                 clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
758         }
759         Activate();
760 }
761
762 /*
763 ================
764 idPhysics_Parametric::SetAxis
765 ================
766 */
767 void idPhysics_Parametric::SetAxis( const idMat3 &newAxis, int id ) {
768         idVec3 masterOrigin;
769         idMat3 masterAxis;
770
771         current.localAngles = newAxis.ToAngles();
772
773         current.angularExtrapolation.SetStartValue( current.localAngles );
774         current.angularInterpolation.SetStartValue( current.localAngles );
775
776         current.localAngles = current.angularExtrapolation.GetCurrentValue( current.time );
777         if ( hasMaster && isOrientated ) {
778                 self->GetMasterPosition( masterOrigin, masterAxis );
779                 current.axis = current.localAngles.ToMat3() * masterAxis;
780                 current.angles = current.axis.ToAngles();
781         }
782         else {
783                 current.axis = current.localAngles.ToMat3();
784                 current.angles = current.localAngles;
785         }
786         if ( clipModel ) {
787                 clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
788         }
789         Activate();
790 }
791
792 /*
793 ================
794 idPhysics_Parametric::Move
795 ================
796 */
797 void idPhysics_Parametric::Translate( const idVec3 &translation, int id ) {
798 }
799
800 /*
801 ================
802 idPhysics_Parametric::Rotate
803 ================
804 */
805 void idPhysics_Parametric::Rotate( const idRotation &rotation, int id ) {
806 }
807
808 /*
809 ================
810 idPhysics_Parametric::GetOrigin
811 ================
812 */
813 const idVec3 &idPhysics_Parametric::GetOrigin( int id ) const {
814         return current.origin;
815 }
816
817 /*
818 ================
819 idPhysics_Parametric::GetAxis
820 ================
821 */
822 const idMat3 &idPhysics_Parametric::GetAxis( int id ) const {
823         return current.axis;
824 }
825
826 /*
827 ================
828 idPhysics_Parametric::GetAngles
829 ================
830 */
831 void idPhysics_Parametric::GetAngles( idAngles &curAngles ) const {
832         curAngles = current.angles;
833 }
834
835 /*
836 ================
837 idPhysics_Parametric::SetLinearVelocity
838 ================
839 */
840 void idPhysics_Parametric::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
841         SetLinearExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, current.origin, newLinearVelocity, vec3_origin );
842         current.linearInterpolation.Init( 0, 0, 0, 0, vec3_zero, vec3_zero );
843         Activate();
844 }
845
846 /*
847 ================
848 idPhysics_Parametric::SetAngularVelocity
849 ================
850 */
851 void idPhysics_Parametric::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
852         idRotation rotation;
853         idVec3 vec;
854         float angle;
855
856         vec = newAngularVelocity;
857         angle = vec.Normalize();
858         rotation.Set( vec3_origin, vec, (float) RAD2DEG( angle ) );
859
860         SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, current.angles, rotation.ToAngles(), ang_zero );
861         current.angularInterpolation.Init( 0, 0, 0, 0, ang_zero, ang_zero );
862         Activate();
863 }
864
865 /*
866 ================
867 idPhysics_Parametric::GetLinearVelocity
868 ================
869 */
870 const idVec3 &idPhysics_Parametric::GetLinearVelocity( int id ) const {
871         static idVec3 curLinearVelocity;
872
873         curLinearVelocity = current.linearExtrapolation.GetCurrentSpeed( gameLocal.time );
874         return curLinearVelocity;
875 }
876
877 /*
878 ================
879 idPhysics_Parametric::GetAngularVelocity
880 ================
881 */
882 const idVec3 &idPhysics_Parametric::GetAngularVelocity( int id ) const {
883         static idVec3 curAngularVelocity;
884         idAngles angles;
885
886         angles = current.angularExtrapolation.GetCurrentSpeed( gameLocal.time );
887         curAngularVelocity = angles.ToAngularVelocity();
888         return curAngularVelocity;
889 }
890
891 /*
892 ================
893 idPhysics_Parametric::DisableClip
894 ================
895 */
896 void idPhysics_Parametric::DisableClip( void ) {
897         if ( clipModel ) {
898                 clipModel->Disable();
899         }
900 }
901
902 /*
903 ================
904 idPhysics_Parametric::EnableClip
905 ================
906 */
907 void idPhysics_Parametric::EnableClip( void ) {
908         if ( clipModel ) {
909                 clipModel->Enable();
910         }
911 }
912
913 /*
914 ================
915 idPhysics_Parametric::UnlinkClip
916 ================
917 */
918 void idPhysics_Parametric::UnlinkClip( void ) {
919         if ( clipModel ) {
920                 clipModel->Unlink();
921         }
922 }
923
924 /*
925 ================
926 idPhysics_Parametric::LinkClip
927 ================
928 */
929 void idPhysics_Parametric::LinkClip( void ) {
930         if ( clipModel ) {
931                 clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
932         }
933 }
934
935 /*
936 ================
937 idPhysics_Parametric::GetBlockingInfo
938 ================
939 */
940 const trace_t *idPhysics_Parametric::GetBlockingInfo( void ) const {
941         return ( isBlocked ? &pushResults : NULL );
942 }
943
944 /*
945 ================
946 idPhysics_Parametric::GetBlockingEntity
947 ================
948 */
949 idEntity *idPhysics_Parametric::GetBlockingEntity( void ) const {
950         if ( isBlocked ) {
951                 return gameLocal.entities[ pushResults.c.entityNum ];
952         }
953         return NULL;
954 }
955
956 /*
957 ================
958 idPhysics_Parametric::SetMaster
959 ================
960 */
961 void idPhysics_Parametric::SetMaster( idEntity *master, const bool orientated ) {
962         idVec3 masterOrigin;
963         idMat3 masterAxis;
964
965         if ( master ) {
966                 if ( !hasMaster ) {
967
968                         // transform from world space to master space
969                         self->GetMasterPosition( masterOrigin, masterAxis );
970                         current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
971                         if ( orientated ) {
972                                 current.localAngles = ( current.axis * masterAxis.Transpose() ).ToAngles();
973                         }
974                         else {
975                                 current.localAngles = current.axis.ToAngles();
976                         }
977
978                         current.linearExtrapolation.SetStartValue( current.localOrigin );
979                         current.angularExtrapolation.SetStartValue( current.localAngles );
980                         hasMaster = true;
981                         isOrientated = orientated;
982                 }
983         }
984         else {
985                 if ( hasMaster ) {
986                         // transform from master space to world space
987                         current.localOrigin = current.origin;
988                         current.localAngles = current.angles;
989                         SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, current.origin, vec3_origin, vec3_origin );
990                         SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, current.angles, ang_zero, ang_zero );
991                         hasMaster = false;
992                 }
993         }
994 }
995
996 /*
997 ================
998 idPhysics_Parametric::GetLinearEndTime
999 ================
1000 */
1001 int idPhysics_Parametric::GetLinearEndTime( void ) const {
1002         if ( current.spline != NULL ) {
1003                 if ( current.spline->GetBoundaryType() != idCurve_Spline<idVec3>::BT_CLOSED ) {
1004                         return current.spline->GetTime( current.spline->GetNumValues() - 1 );
1005                 } else {
1006                         return 0;
1007                 }
1008         } else if ( current.linearInterpolation.GetDuration() != 0 ) {
1009                 return current.linearInterpolation.GetEndTime();
1010         } else {
1011                 return current.linearExtrapolation.GetEndTime();
1012         }
1013 }
1014
1015 /*
1016 ================
1017 idPhysics_Parametric::GetAngularEndTime
1018 ================
1019 */
1020 int idPhysics_Parametric::GetAngularEndTime( void ) const {
1021         if ( current.angularInterpolation.GetDuration() != 0 ) {
1022                 return current.angularInterpolation.GetEndTime();
1023         } else {
1024                 return current.angularExtrapolation.GetEndTime();
1025         }
1026 }
1027
1028 /*
1029 ================
1030 idPhysics_Parametric::WriteToSnapshot
1031 ================
1032 */
1033 void idPhysics_Parametric::WriteToSnapshot( idBitMsgDelta &msg ) const {
1034         msg.WriteLong( current.time );
1035         msg.WriteLong( current.atRest );
1036         msg.WriteFloat( current.origin[0] );
1037         msg.WriteFloat( current.origin[1] );
1038         msg.WriteFloat( current.origin[2] );
1039         msg.WriteFloat( current.angles[0] );
1040         msg.WriteFloat( current.angles[1] );
1041         msg.WriteFloat( current.angles[2] );
1042         msg.WriteDeltaFloat( current.origin[0], current.localOrigin[0] );
1043         msg.WriteDeltaFloat( current.origin[1], current.localOrigin[1] );
1044         msg.WriteDeltaFloat( current.origin[2], current.localOrigin[2] );
1045         msg.WriteDeltaFloat( current.angles[0], current.localAngles[0] );
1046         msg.WriteDeltaFloat( current.angles[1], current.localAngles[1] );
1047         msg.WriteDeltaFloat( current.angles[2], current.localAngles[2] );
1048
1049         msg.WriteBits( current.linearExtrapolation.GetExtrapolationType(), 8 );
1050         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetStartTime() );
1051         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetDuration() );
1052         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetStartValue()[0] );
1053         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetStartValue()[1] );
1054         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetStartValue()[2] );
1055         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetSpeed()[0] );
1056         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetSpeed()[1] );
1057         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetSpeed()[2] );
1058         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetBaseSpeed()[0] );
1059         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetBaseSpeed()[1] );
1060         msg.WriteDeltaFloat( 0.0f, current.linearExtrapolation.GetBaseSpeed()[2] );
1061
1062         msg.WriteBits( current.angularExtrapolation.GetExtrapolationType(), 8 );
1063         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetStartTime() );
1064         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetDuration() );
1065         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetStartValue()[0] );
1066         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetStartValue()[1] );
1067         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetStartValue()[2] );
1068         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetSpeed()[0] );
1069         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetSpeed()[1] );
1070         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetSpeed()[2] );
1071         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetBaseSpeed()[0] );
1072         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetBaseSpeed()[1] );
1073         msg.WriteDeltaFloat( 0.0f, current.angularExtrapolation.GetBaseSpeed()[2] );
1074
1075         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetStartTime() );
1076         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetAcceleration() );
1077         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetDeceleration() );
1078         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetDuration() );
1079         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetStartValue()[0] );
1080         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetStartValue()[1] );
1081         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetStartValue()[2] );
1082         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetEndValue()[0] );
1083         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetEndValue()[1] );
1084         msg.WriteDeltaFloat( 0.0f, current.linearInterpolation.GetEndValue()[2] );
1085
1086         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetStartTime() );
1087         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetAcceleration() );
1088         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetDeceleration() );
1089         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetDuration() );
1090         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetStartValue()[0] );
1091         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetStartValue()[1] );
1092         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetStartValue()[2] );
1093         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetEndValue()[0] );
1094         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetEndValue()[1] );
1095         msg.WriteDeltaFloat( 0.0f, current.angularInterpolation.GetEndValue()[2] );
1096 }
1097
1098 /*
1099 ================
1100 idPhysics_Parametric::ReadFromSnapshot
1101 ================
1102 */
1103 void idPhysics_Parametric::ReadFromSnapshot( const idBitMsgDelta &msg ) {
1104         extrapolation_t linearType, angularType;
1105         float startTime, duration, accelTime, decelTime;
1106         idVec3 linearStartValue, linearSpeed, linearBaseSpeed, startPos, endPos;
1107         idAngles angularStartValue, angularSpeed, angularBaseSpeed, startAng, endAng;
1108
1109         current.time = msg.ReadLong();
1110         current.atRest = msg.ReadLong();
1111         current.origin[0] = msg.ReadFloat();
1112         current.origin[1] = msg.ReadFloat();
1113         current.origin[2] = msg.ReadFloat();
1114         current.angles[0] = msg.ReadFloat();
1115         current.angles[1] = msg.ReadFloat();
1116         current.angles[2] = msg.ReadFloat();
1117         current.localOrigin[0] = msg.ReadDeltaFloat( current.origin[0] );
1118         current.localOrigin[1] = msg.ReadDeltaFloat( current.origin[1] );
1119         current.localOrigin[2] = msg.ReadDeltaFloat( current.origin[2] );
1120         current.localAngles[0] = msg.ReadDeltaFloat( current.angles[0] );
1121         current.localAngles[1] = msg.ReadDeltaFloat( current.angles[1] );
1122         current.localAngles[2] = msg.ReadDeltaFloat( current.angles[2] );
1123
1124         linearType = (extrapolation_t) msg.ReadBits( 8 );
1125         startTime = msg.ReadDeltaFloat( 0.0f );
1126         duration = msg.ReadDeltaFloat( 0.0f );
1127         linearStartValue[0] = msg.ReadDeltaFloat( 0.0f );
1128         linearStartValue[1] = msg.ReadDeltaFloat( 0.0f );
1129         linearStartValue[2] = msg.ReadDeltaFloat( 0.0f );
1130         linearSpeed[0] = msg.ReadDeltaFloat( 0.0f );
1131         linearSpeed[1] = msg.ReadDeltaFloat( 0.0f );
1132         linearSpeed[2] = msg.ReadDeltaFloat( 0.0f );
1133         linearBaseSpeed[0] = msg.ReadDeltaFloat( 0.0f );
1134         linearBaseSpeed[1] = msg.ReadDeltaFloat( 0.0f );
1135         linearBaseSpeed[2] = msg.ReadDeltaFloat( 0.0f );
1136         current.linearExtrapolation.Init( startTime, duration, linearStartValue, linearBaseSpeed, linearSpeed, linearType );
1137
1138         angularType = (extrapolation_t) msg.ReadBits( 8 );
1139         startTime = msg.ReadDeltaFloat( 0.0f );
1140         duration = msg.ReadDeltaFloat( 0.0f );
1141         angularStartValue[0] = msg.ReadDeltaFloat( 0.0f );
1142         angularStartValue[1] = msg.ReadDeltaFloat( 0.0f );
1143         angularStartValue[2] = msg.ReadDeltaFloat( 0.0f );
1144         angularSpeed[0] = msg.ReadDeltaFloat( 0.0f );
1145         angularSpeed[1] = msg.ReadDeltaFloat( 0.0f );
1146         angularSpeed[2] = msg.ReadDeltaFloat( 0.0f );
1147         angularBaseSpeed[0] = msg.ReadDeltaFloat( 0.0f );
1148         angularBaseSpeed[1] = msg.ReadDeltaFloat( 0.0f );
1149         angularBaseSpeed[2] = msg.ReadDeltaFloat( 0.0f );
1150         current.angularExtrapolation.Init( startTime, duration, angularStartValue, angularBaseSpeed, angularSpeed, angularType );
1151
1152         startTime = msg.ReadDeltaFloat( 0.0f );
1153         accelTime = msg.ReadDeltaFloat( 0.0f );
1154         decelTime = msg.ReadDeltaFloat( 0.0f );
1155         duration = msg.ReadDeltaFloat( 0.0f );
1156         startPos[0] = msg.ReadDeltaFloat( 0.0f );
1157         startPos[1] = msg.ReadDeltaFloat( 0.0f );
1158         startPos[2] = msg.ReadDeltaFloat( 0.0f );
1159         endPos[0] = msg.ReadDeltaFloat( 0.0f );
1160         endPos[1] = msg.ReadDeltaFloat( 0.0f );
1161         endPos[2] = msg.ReadDeltaFloat( 0.0f );
1162         current.linearInterpolation.Init( startTime, accelTime, decelTime, duration, startPos, endPos );
1163
1164         startTime = msg.ReadDeltaFloat( 0.0f );
1165         accelTime = msg.ReadDeltaFloat( 0.0f );
1166         decelTime = msg.ReadDeltaFloat( 0.0f );
1167         duration = msg.ReadDeltaFloat( 0.0f );
1168         startAng[0] = msg.ReadDeltaFloat( 0.0f );
1169         startAng[1] = msg.ReadDeltaFloat( 0.0f );
1170         startAng[2] = msg.ReadDeltaFloat( 0.0f );
1171         endAng[0] = msg.ReadDeltaFloat( 0.0f );
1172         endAng[1] = msg.ReadDeltaFloat( 0.0f );
1173         endAng[2] = msg.ReadDeltaFloat( 0.0f );
1174         current.angularInterpolation.Init( startTime, accelTime, decelTime, duration, startAng, endAng );
1175
1176         current.axis = current.angles.ToMat3();
1177
1178         if ( clipModel ) {
1179                 clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
1180         }
1181 }