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