DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Physics_Parametric.cpp (29312B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition 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 BFG Edition 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 #pragma hdrstop
     30 #include "../../idlib/precompiled.h"
     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() {
     44 	current.atRest = -1;
     45 	self->BecomeActive( TH_PHYSICS );
     46 }
     47 
     48 /*
     49 ================
     50 idPhysics_Parametric::TestIfAtRest
     51 ================
     52 */
     53 bool idPhysics_Parametric::TestIfAtRest() 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() {
     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() {
    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() {
    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() 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() const {
    359 	return current.linearExtrapolation.GetExtrapolationType();
    360 }
    361 
    362 /*
    363 ================
    364 idPhysics_Parametric::GetAngularExtrapolationType
    365 ================
    366 */
    367 extrapolation_t idPhysics_Parametric::GetAngularExtrapolationType() 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() const {
    422 	return current.spline;
    423 }
    424 
    425 /*
    426 ================
    427 idPhysics_Parametric::GetSplineAcceleration
    428 ================
    429 */
    430 int idPhysics_Parametric::GetSplineAcceleration() const {
    431 	return current.splineInterpolate.GetAcceleration();
    432 }
    433 
    434 /*
    435 ================
    436 idPhysics_Parametric::GetSplineDeceleration
    437 ================
    438 */
    439 int idPhysics_Parametric::GetSplineDeceleration() const {
    440 	return current.splineInterpolate.GetDeceleration();
    441 }
    442 
    443 /*
    444 ================
    445 idPhysics_Parametric::UsingSplineAngles
    446 ================
    447 */
    448 bool idPhysics_Parametric::UsingSplineAngles() 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() 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 			if ( clipModel ) {
    632 				clipModel->Link( gameLocal.clip, self, 0, oldOrigin, oldAxis );
    633 			}
    634 			current.localOrigin = oldLocalOrigin;
    635 			current.origin = oldOrigin;
    636 			current.localAngles = oldLocalAngles;
    637 			current.angles = oldAngles;
    638 			current.axis = oldAxis;
    639 			isBlocked = true;
    640 			return false;
    641 		}
    642 
    643 		current.angles = current.axis.ToAngles();
    644 	}
    645 
    646 	if ( clipModel ) {
    647 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    648 	}
    649 
    650 	current.time = endTimeMSec;
    651 
    652 	if ( TestIfAtRest() ) {
    653 		Rest();
    654 	}
    655 
    656 	return ( current.origin != oldOrigin || current.axis != oldAxis );
    657 }
    658 
    659 /*
    660 ================
    661 Sets the currentInterpolated state based on previous, next, and the fraction.
    662 ================
    663 */
    664 bool idPhysics_Parametric::Interpolate( const float fraction ) {
    665 
    666 	if( self->GetNumSnapshotsReceived() <= 1 ) {
    667 		return false;
    668 	}
    669 
    670 	idVec3 oldOrigin = current.origin;
    671 	idMat3 oldAxis = current.axis;
    672 
    673 	const bool hasChanged = InterpolatePhysicsState( current, previous, next, fraction );
    674 	
    675 	gameLocal.push.ClipPush( pushResults, self, pushFlags, oldOrigin, oldAxis, current.origin, current.axis );
    676 
    677 	if ( clipModel ) {
    678 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    679 	}
    680 
    681 	return hasChanged;
    682 }
    683 
    684 /*
    685 ================
    686 idPhysics_Parametric::UpdateTime
    687 ================
    688 */
    689 void idPhysics_Parametric::UpdateTime( int endTimeMSec ) {
    690 	int timeLeap = endTimeMSec - current.time;
    691 
    692 	current.time = endTimeMSec;
    693 	// move the trajectory start times to sync the trajectory with the current endTime
    694 	current.linearExtrapolation.SetStartTime( current.linearExtrapolation.GetStartTime() + timeLeap );
    695 	current.angularExtrapolation.SetStartTime( current.angularExtrapolation.GetStartTime() + timeLeap );
    696 	current.linearInterpolation.SetStartTime( current.linearInterpolation.GetStartTime() + timeLeap );
    697 	current.angularInterpolation.SetStartTime( current.angularInterpolation.GetStartTime() + timeLeap );
    698 	if ( current.spline != NULL ) {
    699 		current.spline->ShiftTime( timeLeap );
    700 		current.splineInterpolate.SetStartTime( current.splineInterpolate.GetStartTime() + timeLeap );
    701 	}
    702 }
    703 
    704 /*
    705 ================
    706 idPhysics_Parametric::GetTime
    707 ================
    708 */
    709 int idPhysics_Parametric::GetTime() const {
    710 	return current.time;
    711 }
    712 
    713 /*
    714 ================
    715 idPhysics_Parametric::IsAtRest
    716 ================
    717 */
    718 bool idPhysics_Parametric::IsAtRest() const {
    719 	return current.atRest >= 0;
    720 }
    721 
    722 /*
    723 ================
    724 idPhysics_Parametric::GetRestStartTime
    725 ================
    726 */
    727 int idPhysics_Parametric::GetRestStartTime() const {
    728 	return current.atRest;
    729 }
    730 
    731 /*
    732 ================
    733 idPhysics_Parametric::IsPushable
    734 ================
    735 */
    736 bool idPhysics_Parametric::IsPushable() const {
    737 	return false;
    738 }
    739 
    740 /*
    741 ================
    742 idPhysics_Parametric::SaveState
    743 ================
    744 */
    745 void idPhysics_Parametric::SaveState() {
    746 	saved = current;
    747 }
    748 
    749 /*
    750 ================
    751 idPhysics_Parametric::RestoreState
    752 ================
    753 */
    754 void idPhysics_Parametric::RestoreState() {
    755 
    756 	current = saved;
    757 
    758 	if ( clipModel ) {
    759 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    760 	}
    761 }
    762 
    763 /*
    764 ================
    765 idPhysics_Parametric::SetOrigin
    766 ================
    767 */
    768 void idPhysics_Parametric::SetOrigin( const idVec3 &newOrigin, int id ) {
    769 	idVec3 masterOrigin;
    770 	idMat3 masterAxis;
    771 
    772 	current.linearExtrapolation.SetStartValue( newOrigin );
    773 	current.linearInterpolation.SetStartValue( newOrigin );
    774 
    775 	current.localOrigin = current.linearExtrapolation.GetCurrentValue( current.time );
    776 	if ( hasMaster ) {
    777 		self->GetMasterPosition( masterOrigin, masterAxis );
    778 		current.origin = masterOrigin + current.localOrigin * masterAxis;
    779 	}
    780 	else {
    781 		current.origin = current.localOrigin;
    782 	}
    783 	if ( clipModel ) {
    784 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    785 	}
    786 	Activate();
    787 }
    788 
    789 /*
    790 ================
    791 idPhysics_Parametric::SetAxis
    792 ================
    793 */
    794 void idPhysics_Parametric::SetAxis( const idMat3 &newAxis, int id ) {
    795 	idVec3 masterOrigin;
    796 	idMat3 masterAxis;
    797 
    798 	current.localAngles = newAxis.ToAngles();
    799 
    800 	current.angularExtrapolation.SetStartValue( current.localAngles );
    801 	current.angularInterpolation.SetStartValue( current.localAngles );
    802 
    803 	current.localAngles = current.angularExtrapolation.GetCurrentValue( current.time );
    804 	if ( hasMaster && isOrientated ) {
    805 		self->GetMasterPosition( masterOrigin, masterAxis );
    806 		current.axis = current.localAngles.ToMat3() * masterAxis;
    807 		current.angles = current.axis.ToAngles();
    808 	}
    809 	else {
    810 		current.axis = current.localAngles.ToMat3();
    811 		current.angles = current.localAngles;
    812 	}
    813 	if ( clipModel ) {
    814 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    815 	}
    816 	Activate();
    817 }
    818 
    819 /*
    820 ================
    821 idPhysics_Parametric::Move
    822 ================
    823 */
    824 void idPhysics_Parametric::Translate( const idVec3 &translation, int id ) {
    825 }
    826 
    827 /*
    828 ================
    829 idPhysics_Parametric::Rotate
    830 ================
    831 */
    832 void idPhysics_Parametric::Rotate( const idRotation &rotation, int id ) {
    833 }
    834 
    835 /*
    836 ================
    837 idPhysics_Parametric::GetOrigin
    838 ================
    839 */
    840 const idVec3 &idPhysics_Parametric::GetOrigin( int id ) const {
    841 	return current.origin;
    842 }
    843 
    844 /*
    845 ================
    846 idPhysics_Parametric::GetAxis
    847 ================
    848 */
    849 const idMat3 &idPhysics_Parametric::GetAxis( int id ) const {
    850 	return current.axis;
    851 }
    852 
    853 /*
    854 ================
    855 idPhysics_Parametric::GetAngles
    856 ================
    857 */
    858 void idPhysics_Parametric::GetAngles( idAngles &curAngles ) const {
    859 	curAngles = current.angles;
    860 }
    861 
    862 /*
    863 ================
    864 idPhysics_Parametric::SetLinearVelocity
    865 ================
    866 */
    867 void idPhysics_Parametric::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
    868 	SetLinearExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, current.origin, newLinearVelocity, vec3_origin );
    869 	current.linearInterpolation.Init( 0, 0, 0, 0, vec3_zero, vec3_zero );
    870 	Activate();
    871 }
    872 
    873 /*
    874 ================
    875 idPhysics_Parametric::SetAngularVelocity
    876 ================
    877 */
    878 void idPhysics_Parametric::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
    879 	idRotation rotation;
    880 	idVec3 vec;
    881 	float angle;
    882 
    883 	vec = newAngularVelocity;
    884 	angle = vec.Normalize();
    885 	rotation.Set( vec3_origin, vec, (float) RAD2DEG( angle ) );
    886 
    887 	SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, current.angles, rotation.ToAngles(), ang_zero );
    888 	current.angularInterpolation.Init( 0, 0, 0, 0, ang_zero, ang_zero );
    889 	Activate();
    890 }
    891 
    892 /*
    893 ================
    894 idPhysics_Parametric::GetLinearVelocity
    895 ================
    896 */
    897 const idVec3 &idPhysics_Parametric::GetLinearVelocity( int id ) const {
    898 	static idVec3 curLinearVelocity;
    899 
    900 	curLinearVelocity = current.linearExtrapolation.GetCurrentSpeed( gameLocal.time );
    901 	return curLinearVelocity;
    902 }
    903 
    904 /*
    905 ================
    906 idPhysics_Parametric::GetAngularVelocity
    907 ================
    908 */
    909 const idVec3 &idPhysics_Parametric::GetAngularVelocity( int id ) const {
    910 	static idVec3 curAngularVelocity;
    911 	idAngles angles;
    912 
    913 	angles = current.angularExtrapolation.GetCurrentSpeed( gameLocal.time );
    914 	curAngularVelocity = angles.ToAngularVelocity();
    915 	return curAngularVelocity;
    916 }
    917 
    918 /*
    919 ================
    920 idPhysics_Parametric::DisableClip
    921 ================
    922 */
    923 void idPhysics_Parametric::DisableClip() {
    924 	if ( clipModel ) {
    925 		clipModel->Disable();
    926 	}
    927 }
    928 
    929 /*
    930 ================
    931 idPhysics_Parametric::EnableClip
    932 ================
    933 */
    934 void idPhysics_Parametric::EnableClip() {
    935 	if ( clipModel ) {
    936 		clipModel->Enable();
    937 	}
    938 }
    939 
    940 /*
    941 ================
    942 idPhysics_Parametric::UnlinkClip
    943 ================
    944 */
    945 void idPhysics_Parametric::UnlinkClip() {
    946 	if ( clipModel ) {
    947 		clipModel->Unlink();
    948 	}
    949 }
    950 
    951 /*
    952 ================
    953 idPhysics_Parametric::LinkClip
    954 ================
    955 */
    956 void idPhysics_Parametric::LinkClip() {
    957 	if ( clipModel ) {
    958 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    959 	}
    960 }
    961 
    962 /*
    963 ================
    964 idPhysics_Parametric::GetBlockingInfo
    965 ================
    966 */
    967 const trace_t *idPhysics_Parametric::GetBlockingInfo() const {
    968 	return ( isBlocked ? &pushResults : NULL );
    969 }
    970 
    971 /*
    972 ================
    973 idPhysics_Parametric::GetBlockingEntity
    974 ================
    975 */
    976 idEntity *idPhysics_Parametric::GetBlockingEntity() const {
    977 	if ( isBlocked ) {
    978 		return gameLocal.entities[ pushResults.c.entityNum ];
    979 	}
    980 	return NULL;
    981 }
    982 
    983 /*
    984 ================
    985 idPhysics_Parametric::SetMaster
    986 ================
    987 */
    988 void idPhysics_Parametric::SetMaster( idEntity *master, const bool orientated ) {
    989 	idVec3 masterOrigin;
    990 	idMat3 masterAxis;
    991 
    992 	if ( master ) {
    993 		if ( !hasMaster ) {
    994 
    995 			// transform from world space to master space
    996 			self->GetMasterPosition( masterOrigin, masterAxis );
    997 			current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
    998 			if ( orientated ) {
    999 				current.localAngles = ( current.axis * masterAxis.Transpose() ).ToAngles();
   1000 			}
   1001 			else {
   1002 				current.localAngles = current.axis.ToAngles();
   1003 			}
   1004 
   1005 			current.linearExtrapolation.SetStartValue( current.localOrigin );
   1006 			current.angularExtrapolation.SetStartValue( current.localAngles );
   1007 			hasMaster = true;
   1008 			isOrientated = orientated;
   1009 		}
   1010 	}
   1011 	else {
   1012 		if ( hasMaster ) {
   1013 			// transform from master space to world space
   1014 			current.localOrigin = current.origin;
   1015 			current.localAngles = current.angles;
   1016 			SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, current.origin, vec3_origin, vec3_origin );
   1017 			SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, current.angles, ang_zero, ang_zero );
   1018 			hasMaster = false;
   1019 		}
   1020 	}
   1021 }
   1022 
   1023 /*
   1024 ================
   1025 idPhysics_Parametric::GetLinearEndTime
   1026 ================
   1027 */
   1028 int idPhysics_Parametric::GetLinearEndTime() const {
   1029 	if ( current.spline != NULL ) {
   1030 		if ( current.spline->GetBoundaryType() != idCurve_Spline<idVec3>::BT_CLOSED ) {
   1031 			return current.spline->GetTime( current.spline->GetNumValues() - 1 );
   1032 		} else {
   1033 			return 0;
   1034 		}
   1035 	} else if ( current.linearInterpolation.GetDuration() != 0 ) {
   1036 		return current.linearInterpolation.GetEndTime();
   1037 	} else {
   1038 		return current.linearExtrapolation.GetEndTime();
   1039 	}
   1040 }
   1041 
   1042 /*
   1043 ================
   1044 idPhysics_Parametric::GetAngularEndTime
   1045 ================
   1046 */
   1047 int idPhysics_Parametric::GetAngularEndTime() const {
   1048 	if ( current.angularInterpolation.GetDuration() != 0 ) {
   1049 		return current.angularInterpolation.GetEndTime();
   1050 	} else {
   1051 		return current.angularExtrapolation.GetEndTime();
   1052 	}
   1053 }
   1054 
   1055 /*
   1056 ================
   1057 idPhysics_Parametric::WriteToSnapshot
   1058 ================
   1059 */
   1060 void idPhysics_Parametric::WriteToSnapshot( idBitMsg &msg ) const {
   1061 
   1062 	const idQuat currentQuat = current.axis.ToQuat();
   1063 	
   1064 	WriteFloatArray( msg, current.origin );
   1065 	WriteFloatArray( msg, currentQuat );
   1066 }
   1067 
   1068 /*
   1069 ================
   1070 idPhysics_Parametric::ReadFromSnapshot
   1071 ================
   1072 */
   1073 void idPhysics_Parametric::ReadFromSnapshot( const idBitMsg &msg ) {
   1074 
   1075 	previous = next;
   1076 
   1077 	next.origin = ReadFloatArray< idVec3 >( msg );
   1078 	next.axis = ReadFloatArray< idQuat >( msg );
   1079 
   1080 	if( self->GetNumSnapshotsReceived() <= 1 ) {
   1081 		current.origin = next.origin;
   1082 		previous.origin = next.origin;
   1083 		current.axis = next.axis.ToMat3();
   1084 		previous.axis = next.axis;
   1085 	}
   1086 }