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 "Entity.h"
31
32 #include "physics/Physics_Parametric.h"
33
CLASS_DECLARATION(idPhysics_Base,idPhysics_Parametric)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 */
TestIfAtRest(void) const53 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 */
Rest(void)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 */
idPhysics_Parametric(void)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 */
~idPhysics_Parametric(void)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 */
idPhysics_Parametric_SavePState(idSaveGame * savefile,const parametricPState_t & state)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 */
idPhysics_Parametric_RestorePState(idRestoreGame * savefile,parametricPState_t & state)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 */
Save(idSaveGame * savefile) const272 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 */
Restore(idRestoreGame * savefile)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 */
SetPusher(int flags)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 */
IsPusher(void) const325 bool idPhysics_Parametric::IsPusher( void ) const {
326 return isPusher;
327 }
328
329 /*
330 ================
331 idPhysics_Parametric::SetLinearExtrapolation
332 ================
333 */
SetLinearExtrapolation(extrapolation_t type,int time,int duration,const idVec3 & base,const idVec3 & speed,const idVec3 & baseSpeed)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 */
SetAngularExtrapolation(extrapolation_t type,int time,int duration,const idAngles & base,const idAngles & speed,const idAngles & baseSpeed)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 */
GetLinearExtrapolationType(void) const358 extrapolation_t idPhysics_Parametric::GetLinearExtrapolationType( void ) const {
359 return current.linearExtrapolation.GetExtrapolationType();
360 }
361
362 /*
363 ================
364 idPhysics_Parametric::GetAngularExtrapolationType
365 ================
366 */
GetAngularExtrapolationType(void) const367 extrapolation_t idPhysics_Parametric::GetAngularExtrapolationType( void ) const {
368 return current.angularExtrapolation.GetExtrapolationType();
369 }
370
371 /*
372 ================
373 idPhysics_Parametric::SetLinearInterpolation
374 ================
375 */
SetLinearInterpolation(int time,int accelTime,int decelTime,int duration,const idVec3 & startPos,const idVec3 & endPos)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 */
SetAngularInterpolation(int time,int accelTime,int decelTime,int duration,const idAngles & startAng,const idAngles & endAng)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 */
SetSpline(idCurve_Spline<idVec3> * spline,int accelTime,int decelTime,bool useSplineAngles)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 */
GetSpline(void) const421 idCurve_Spline<idVec3> *idPhysics_Parametric::GetSpline( void ) const {
422 return current.spline;
423 }
424
425 /*
426 ================
427 idPhysics_Parametric::GetSplineAcceleration
428 ================
429 */
GetSplineAcceleration(void) const430 int idPhysics_Parametric::GetSplineAcceleration( void ) const {
431 return current.splineInterpolate.GetAcceleration();
432 }
433
434 /*
435 ================
436 idPhysics_Parametric::GetSplineDeceleration
437 ================
438 */
GetSplineDeceleration(void) const439 int idPhysics_Parametric::GetSplineDeceleration( void ) const {
440 return current.splineInterpolate.GetDeceleration();
441 }
442
443 /*
444 ================
445 idPhysics_Parametric::UsingSplineAngles
446 ================
447 */
UsingSplineAngles(void) const448 bool idPhysics_Parametric::UsingSplineAngles( void ) const {
449 return current.useSplineAngles;
450 }
451
452 /*
453 ================
454 idPhysics_Parametric::GetLocalOrigin
455 ================
456 */
GetLocalOrigin(idVec3 & curOrigin) const457 void idPhysics_Parametric::GetLocalOrigin( idVec3 &curOrigin ) const {
458 curOrigin = current.localOrigin;
459 }
460
461 /*
462 ================
463 idPhysics_Parametric::GetLocalAngles
464 ================
465 */
GetLocalAngles(idAngles & curAngles) const466 void idPhysics_Parametric::GetLocalAngles( idAngles &curAngles ) const {
467 curAngles = current.localAngles;
468 }
469
470 /*
471 ================
472 idPhysics_Parametric::SetClipModel
473 ================
474 */
SetClipModel(idClipModel * model,float density,int id,bool freeOld)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 */
GetClipModel(int id) const492 idClipModel *idPhysics_Parametric::GetClipModel( int id ) const {
493 return clipModel;
494 }
495
496 /*
497 ================
498 idPhysics_Parametric::GetNumClipModels
499 ================
500 */
GetNumClipModels(void) const501 int idPhysics_Parametric::GetNumClipModels( void ) const {
502 return ( clipModel != NULL );
503 }
504
505 /*
506 ================
507 idPhysics_Parametric::SetMass
508 ================
509 */
SetMass(float mass,int id)510 void idPhysics_Parametric::SetMass( float mass, int id ) {
511 }
512
513 /*
514 ================
515 idPhysics_Parametric::GetMass
516 ================
517 */
GetMass(int id) const518 float idPhysics_Parametric::GetMass( int id ) const {
519 return 0.0f;
520 }
521
522 /*
523 ================
524 idPhysics_Parametric::SetClipMask
525 ================
526 */
SetContents(int contents,int id)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 */
GetContents(int id) const538 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 */
GetBounds(int id) const550 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 */
GetAbsBounds(int id) const562 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 */
Evaluate(int timeStepMSec,int endTimeMSec)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 */
UpdateTime(int endTimeMSec)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 */
GetTime(void) const682 int idPhysics_Parametric::GetTime( void ) const {
683 return current.time;
684 }
685
686 /*
687 ================
688 idPhysics_Parametric::IsAtRest
689 ================
690 */
IsAtRest(void) const691 bool idPhysics_Parametric::IsAtRest( void ) const {
692 return current.atRest >= 0;
693 }
694
695 /*
696 ================
697 idPhysics_Parametric::GetRestStartTime
698 ================
699 */
GetRestStartTime(void) const700 int idPhysics_Parametric::GetRestStartTime( void ) const {
701 return current.atRest;
702 }
703
704 /*
705 ================
706 idPhysics_Parametric::IsPushable
707 ================
708 */
IsPushable(void) const709 bool idPhysics_Parametric::IsPushable( void ) const {
710 return false;
711 }
712
713 /*
714 ================
715 idPhysics_Parametric::SaveState
716 ================
717 */
SaveState(void)718 void idPhysics_Parametric::SaveState( void ) {
719 saved = current;
720 }
721
722 /*
723 ================
724 idPhysics_Parametric::RestoreState
725 ================
726 */
RestoreState(void)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 */
SetOrigin(const idVec3 & newOrigin,int id)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 */
SetAxis(const idMat3 & newAxis,int id)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 */
Translate(const idVec3 & translation,int id)797 void idPhysics_Parametric::Translate( const idVec3 &translation, int id ) {
798 }
799
800 /*
801 ================
802 idPhysics_Parametric::Rotate
803 ================
804 */
Rotate(const idRotation & rotation,int id)805 void idPhysics_Parametric::Rotate( const idRotation &rotation, int id ) {
806 }
807
808 /*
809 ================
810 idPhysics_Parametric::GetOrigin
811 ================
812 */
GetOrigin(int id) const813 const idVec3 &idPhysics_Parametric::GetOrigin( int id ) const {
814 return current.origin;
815 }
816
817 /*
818 ================
819 idPhysics_Parametric::GetAxis
820 ================
821 */
GetAxis(int id) const822 const idMat3 &idPhysics_Parametric::GetAxis( int id ) const {
823 return current.axis;
824 }
825
826 /*
827 ================
828 idPhysics_Parametric::GetAngles
829 ================
830 */
GetAngles(idAngles & curAngles) const831 void idPhysics_Parametric::GetAngles( idAngles &curAngles ) const {
832 curAngles = current.angles;
833 }
834
835 /*
836 ================
837 idPhysics_Parametric::SetLinearVelocity
838 ================
839 */
SetLinearVelocity(const idVec3 & newLinearVelocity,int id)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 */
SetAngularVelocity(const idVec3 & newAngularVelocity,int id)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 */
GetLinearVelocity(int id) const870 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 */
GetAngularVelocity(int id) const882 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 */
DisableClip(void)896 void idPhysics_Parametric::DisableClip( void ) {
897 if ( clipModel ) {
898 clipModel->Disable();
899 }
900 }
901
902 /*
903 ================
904 idPhysics_Parametric::EnableClip
905 ================
906 */
EnableClip(void)907 void idPhysics_Parametric::EnableClip( void ) {
908 if ( clipModel ) {
909 clipModel->Enable();
910 }
911 }
912
913 /*
914 ================
915 idPhysics_Parametric::UnlinkClip
916 ================
917 */
UnlinkClip(void)918 void idPhysics_Parametric::UnlinkClip( void ) {
919 if ( clipModel ) {
920 clipModel->Unlink();
921 }
922 }
923
924 /*
925 ================
926 idPhysics_Parametric::LinkClip
927 ================
928 */
LinkClip(void)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 */
GetBlockingInfo(void) const940 const trace_t *idPhysics_Parametric::GetBlockingInfo( void ) const {
941 return ( isBlocked ? &pushResults : NULL );
942 }
943
944 /*
945 ================
946 idPhysics_Parametric::GetBlockingEntity
947 ================
948 */
GetBlockingEntity(void) const949 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 */
SetMaster(idEntity * master,const bool orientated)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 */
GetLinearEndTime(void) const1001 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 */
GetAngularEndTime(void) const1020 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 */
WriteToSnapshot(idBitMsgDelta & msg) const1033 void idPhysics_Parametric::WriteToSnapshot( idBitMsgDelta &msg ) const {
1034 msg.WriteInt( current.time );
1035 msg.WriteInt( 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 */
ReadFromSnapshot(const idBitMsgDelta & msg)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.ReadInt();
1110 current.atRest = msg.ReadInt();
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 }
1182