DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Physics_Static.cpp (20050B)


      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, idPhysics_Static )
     35 END_CLASS
     36 
     37 /*
     38 ================
     39 idPhysics_Static::idPhysics_Static
     40 ================
     41 */
     42 idPhysics_Static::idPhysics_Static() {
     43 	self = NULL;
     44 	clipModel = NULL;
     45 	current.origin.Zero();
     46 	current.axis.Identity();
     47 	current.localOrigin.Zero();
     48 	current.localAxis.Identity();
     49 
     50 	next = ConvertPStateToInterpolateState( current );
     51 	previous = next;
     52 
     53 	hasMaster = false;
     54 	isOrientated = false;
     55 }
     56 
     57 /*
     58 ================
     59 idPhysics_Static::~idPhysics_Static
     60 ================
     61 */
     62 idPhysics_Static::~idPhysics_Static() {
     63 	if ( self && self->GetPhysics() == this ) {
     64 		self->SetPhysics( NULL );
     65 	}
     66 	idForce::DeletePhysics( this );
     67 	if ( clipModel ) {
     68 		delete clipModel;
     69 	}
     70 }
     71 
     72 /*
     73 ================
     74 idPhysics_Static::Save
     75 ================
     76 */
     77 void idPhysics_Static::Save( idSaveGame *savefile ) const {
     78 	savefile->WriteObject( self );
     79 
     80 	savefile->WriteVec3( current.origin );
     81 	savefile->WriteMat3( current.axis );
     82 	savefile->WriteVec3( current.localOrigin );
     83 	savefile->WriteMat3( current.localAxis );
     84 	savefile->WriteClipModel( clipModel );
     85 
     86 	savefile->WriteBool( hasMaster );
     87 	savefile->WriteBool( isOrientated );
     88 }
     89 
     90 /*
     91 ================
     92 idPhysics_Static::Restore
     93 ================
     94 */
     95 void idPhysics_Static::Restore( idRestoreGame *savefile ) {
     96 	savefile->ReadObject( reinterpret_cast<idClass *&>( self ) );
     97 
     98 	savefile->ReadVec3( current.origin );
     99 	savefile->ReadMat3( current.axis );
    100 	savefile->ReadVec3( current.localOrigin );
    101 	savefile->ReadMat3( current.localAxis );
    102 	savefile->ReadClipModel( clipModel );
    103 
    104 	savefile->ReadBool( hasMaster );
    105 	savefile->ReadBool( isOrientated );
    106 }
    107 
    108 /*
    109 ================
    110 idPhysics_Static::SetSelf
    111 ================
    112 */
    113 void idPhysics_Static::SetSelf( idEntity *e ) {
    114 	assert( e );
    115 	self = e;
    116 }
    117 
    118 /*
    119 ================
    120 idPhysics_Static::SetClipModel
    121 ================
    122 */
    123 void idPhysics_Static::SetClipModel( idClipModel *model, float density, int id, bool freeOld ) {
    124 	assert( self );
    125 
    126 	if ( clipModel && clipModel != model && freeOld ) {
    127 		delete clipModel;
    128 	}
    129 	clipModel = model;
    130 	if ( clipModel ) {
    131 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    132 	}
    133 }
    134 
    135 /*
    136 ================
    137 idPhysics_Static::GetClipModel
    138 ================
    139 */
    140 idClipModel *idPhysics_Static::GetClipModel( int id ) const {
    141 	if ( clipModel ) {
    142 		return clipModel;
    143 	}
    144 	return gameLocal.clip.DefaultClipModel();
    145 }
    146 
    147 /*
    148 ================
    149 idPhysics_Static::GetNumClipModels
    150 ================
    151 */
    152 int idPhysics_Static::GetNumClipModels() const {
    153 	return ( clipModel != NULL );
    154 }
    155 
    156 /*
    157 ================
    158 idPhysics_Static::SetMass
    159 ================
    160 */
    161 void idPhysics_Static::SetMass( float mass, int id ) {
    162 }
    163 
    164 /*
    165 ================
    166 idPhysics_Static::GetMass
    167 ================
    168 */
    169 float idPhysics_Static::GetMass( int id ) const {
    170 	return 0.0f;
    171 }
    172 
    173 /*
    174 ================
    175 idPhysics_Static::SetContents
    176 ================
    177 */
    178 void idPhysics_Static::SetContents( int contents, int id ) {
    179 	if ( clipModel ) {
    180 		clipModel->SetContents( contents );
    181 	}
    182 }
    183 
    184 /*
    185 ================
    186 idPhysics_Static::GetContents
    187 ================
    188 */
    189 int idPhysics_Static::GetContents( int id ) const {
    190 	if ( clipModel ) {
    191 		return clipModel->GetContents();
    192 	}
    193 	return 0;
    194 }
    195 
    196 /*
    197 ================
    198 idPhysics_Static::SetClipMask
    199 ================
    200 */
    201 void idPhysics_Static::SetClipMask( int mask, int id ) {
    202 }
    203 
    204 /*
    205 ================
    206 idPhysics_Static::GetClipMask
    207 ================
    208 */
    209 int idPhysics_Static::GetClipMask( int id ) const {
    210 	return 0;
    211 }
    212 
    213 /*
    214 ================
    215 idPhysics_Static::GetBounds
    216 ================
    217 */
    218 const idBounds &idPhysics_Static::GetBounds( int id ) const {
    219 	if ( clipModel ) {
    220 		return clipModel->GetBounds();
    221 	}
    222 	return bounds_zero;
    223 }
    224 
    225 /*
    226 ================
    227 idPhysics_Static::GetAbsBounds
    228 ================
    229 */
    230 const idBounds &idPhysics_Static::GetAbsBounds( int id ) const {
    231 	static idBounds absBounds;
    232 
    233 	if ( clipModel ) {
    234 		return clipModel->GetAbsBounds();
    235 	}
    236 	absBounds[0] = absBounds[1] = current.origin;
    237 	return absBounds;
    238 }
    239 
    240 /*
    241 ================
    242 idPhysics_Static::Evaluate
    243 ================
    244 */
    245 bool idPhysics_Static::Evaluate( int timeStepMSec, int endTimeMSec ) {
    246 	idVec3 masterOrigin, oldOrigin;
    247 	idMat3 masterAxis, oldAxis;
    248 
    249 
    250 	if ( hasMaster ) {
    251 		oldOrigin = current.origin;
    252 		oldAxis = current.axis;
    253 
    254 		self->GetMasterPosition( masterOrigin, masterAxis );
    255 		current.origin = masterOrigin + current.localOrigin * masterAxis;
    256 		if ( isOrientated ) {
    257 			current.axis = current.localAxis * masterAxis;
    258 		} else {
    259 			current.axis = current.localAxis;
    260 		}
    261 		if ( clipModel ) {
    262 			clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    263 		}
    264 
    265 		return ( current.origin != oldOrigin || current.axis != oldAxis );
    266 	}
    267 	return false;
    268 }
    269 
    270 /*
    271 ================
    272 idPhysics_Static::Interpolate
    273 ================
    274 */
    275 bool idPhysics_Static::Interpolate( const float fraction ) {
    276 	
    277 	// We only interpolate if we actually get snapshots.
    278 	if( self->GetNumSnapshotsReceived() >= 1 ) {
    279 		current = InterpolateStaticPState( previous, next, fraction );
    280 	}
    281 
    282 	return true;
    283 }
    284 
    285 /*
    286 ================
    287 idPhysics_Static::UpdateTime
    288 ================
    289 */
    290 void idPhysics_Static::UpdateTime( int endTimeMSec ) {
    291 }
    292 
    293 /*
    294 ================
    295 idPhysics_Static::GetTime
    296 ================
    297 */
    298 int idPhysics_Static::GetTime() const {
    299 	return 0;
    300 }
    301 
    302 /*
    303 ================
    304 idPhysics_Static::GetImpactInfo
    305 ================
    306 */
    307 void idPhysics_Static::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
    308 	memset( info, 0, sizeof( *info ) );
    309 }
    310 
    311 /*
    312 ================
    313 idPhysics_Static::ApplyImpulse
    314 ================
    315 */
    316 void idPhysics_Static::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
    317 }
    318 
    319 /*
    320 ================
    321 idPhysics_Static::AddForce
    322 ================
    323 */
    324 void idPhysics_Static::AddForce( const int id, const idVec3 &point, const idVec3 &force ) {
    325 }
    326 
    327 /*
    328 ================
    329 idPhysics_Static::Activate
    330 ================
    331 */
    332 void idPhysics_Static::Activate() {
    333 }
    334 
    335 /*
    336 ================
    337 idPhysics_Static::PutToRest
    338 ================
    339 */
    340 void idPhysics_Static::PutToRest() {
    341 }
    342 
    343 /*
    344 ================
    345 idPhysics_Static::IsAtRest
    346 ================
    347 */
    348 bool idPhysics_Static::IsAtRest() const {
    349 	return true;
    350 }
    351 
    352 /*
    353 ================
    354 idPhysics_Static::GetRestStartTime
    355 ================
    356 */
    357 int idPhysics_Static::GetRestStartTime() const {
    358 	return 0;
    359 }
    360 
    361 /*
    362 ================
    363 idPhysics_Static::IsPushable
    364 ================
    365 */
    366 bool idPhysics_Static::IsPushable() const {
    367 	return false;
    368 }
    369 
    370 /*
    371 ================
    372 idPhysics_Static::SaveState
    373 ================
    374 */
    375 void idPhysics_Static::SaveState() {
    376 }
    377 
    378 /*
    379 ================
    380 idPhysics_Static::RestoreState
    381 ================
    382 */
    383 void idPhysics_Static::RestoreState() {
    384 }
    385 
    386 /*
    387 ================
    388 idPhysics_Static::SetOrigin
    389 ================
    390 */
    391 void idPhysics_Static::SetOrigin( const idVec3 &newOrigin, int id ) {
    392 	idVec3 masterOrigin;
    393 	idMat3 masterAxis;
    394 
    395 	current.localOrigin = newOrigin;
    396 
    397 	if ( hasMaster ) {
    398 		self->GetMasterPosition( masterOrigin, masterAxis );
    399 		current.origin = masterOrigin + newOrigin * masterAxis;
    400 	} else {
    401 		current.origin = newOrigin;
    402 	}
    403 
    404 	if ( clipModel ) {
    405 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    406 	}
    407 
    408 	next = ConvertPStateToInterpolateState( current );
    409 	previous = next;
    410 }
    411 
    412 /*
    413 ================
    414 idPhysics_Static::SetAxis
    415 ================
    416 */
    417 void idPhysics_Static::SetAxis( const idMat3 &newAxis, int id ) {
    418 	idVec3 masterOrigin;
    419 	idMat3 masterAxis;
    420 
    421 	current.localAxis = newAxis;
    422 
    423 	if ( hasMaster && isOrientated ) {
    424 		self->GetMasterPosition( masterOrigin, masterAxis );
    425 		current.axis = newAxis * masterAxis;
    426 	} else {
    427 		current.axis = newAxis;
    428 	}
    429 
    430 	if ( clipModel ) {
    431 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    432 	}
    433 
    434 	next = ConvertPStateToInterpolateState( current );
    435 	previous = next;
    436 }
    437 
    438 
    439 
    440 /*
    441 ================
    442 idPhysics_Static::Translate
    443 ================
    444 */
    445 void idPhysics_Static::Translate( const idVec3 &translation, int id ) {
    446 	current.localOrigin += translation;
    447 	current.origin += translation;
    448 
    449 	if ( clipModel ) {
    450 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    451 	}
    452 }
    453 
    454 /*
    455 ================
    456 idPhysics_Static::Rotate
    457 ================
    458 */
    459 void idPhysics_Static::Rotate( const idRotation &rotation, int id ) {
    460 	idVec3 masterOrigin;
    461 	idMat3 masterAxis;
    462 
    463 	current.origin *= rotation;
    464 	current.axis *= rotation.ToMat3();
    465 
    466 	if ( hasMaster ) {
    467 		self->GetMasterPosition( masterOrigin, masterAxis );
    468 		current.localAxis *= rotation.ToMat3();
    469 		current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
    470 	} else {
    471 		current.localAxis = current.axis;
    472 		current.localOrigin = current.origin;
    473 	}
    474 
    475 	if ( clipModel ) {
    476 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    477 	}
    478 }
    479 
    480 /*
    481 ================
    482 idPhysics_Static::GetOrigin
    483 ================
    484 */
    485 const idVec3 &idPhysics_Static::GetOrigin( int id ) const {
    486 	return current.origin;
    487 }
    488 
    489 /*
    490 ================
    491 idPhysics_Static::GetAxis
    492 ================
    493 */
    494 const idMat3 &idPhysics_Static::GetAxis( int id ) const {
    495 	return current.axis;
    496 }
    497 
    498 /*
    499 ================
    500 idPhysics_Static::SetLinearVelocity
    501 ================
    502 */
    503 void idPhysics_Static::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
    504 }
    505 
    506 /*
    507 ================
    508 idPhysics_Static::SetAngularVelocity
    509 ================
    510 */
    511 void idPhysics_Static::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
    512 }
    513 
    514 /*
    515 ================
    516 idPhysics_Static::GetLinearVelocity
    517 ================
    518 */
    519 const idVec3 &idPhysics_Static::GetLinearVelocity( int id ) const {
    520 	return vec3_origin;
    521 }
    522 
    523 /*
    524 ================
    525 idPhysics_Static::GetAngularVelocity
    526 ================
    527 */
    528 const idVec3 &idPhysics_Static::GetAngularVelocity( int id ) const {
    529 	return vec3_origin;
    530 }
    531 
    532 /*
    533 ================
    534 idPhysics_Static::SetGravity
    535 ================
    536 */
    537 void idPhysics_Static::SetGravity( const idVec3 &newGravity ) {
    538 }
    539 
    540 /*
    541 ================
    542 idPhysics_Static::GetGravity
    543 ================
    544 */
    545 const idVec3 &idPhysics_Static::GetGravity() const {
    546 	static idVec3 gravity( 0, 0, -g_gravity.GetFloat() );
    547 	return gravity;
    548 }
    549 
    550 /*
    551 ================
    552 idPhysics_Static::GetGravityNormal
    553 ================
    554 */
    555 const idVec3 &idPhysics_Static::GetGravityNormal() const {
    556 	static idVec3 gravity( 0, 0, -1 );
    557 	return gravity;
    558 }
    559 
    560 /*
    561 ================
    562 idPhysics_Static::ClipTranslation
    563 ================
    564 */
    565 void idPhysics_Static::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
    566 	if ( model ) {
    567 		gameLocal.clip.TranslationModel( results, current.origin, current.origin + translation,
    568 			clipModel, current.axis, MASK_SOLID, model->Handle(), model->GetOrigin(), model->GetAxis() );
    569 	} else {
    570 		gameLocal.clip.Translation( results, current.origin, current.origin + translation,
    571 			clipModel, current.axis, MASK_SOLID, self );
    572 	}	
    573 }
    574 
    575 /*
    576 ================
    577 idPhysics_Static::ClipRotation
    578 ================
    579 */
    580 void idPhysics_Static::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
    581 	if ( model ) {
    582 		gameLocal.clip.RotationModel( results, current.origin, rotation,
    583 			clipModel, current.axis, MASK_SOLID, model->Handle(), model->GetOrigin(), model->GetAxis() );
    584 	} else {
    585 		gameLocal.clip.Rotation( results, current.origin, rotation, clipModel, current.axis, MASK_SOLID, self );
    586 	}
    587 }
    588 
    589 /*
    590 ================
    591 idPhysics_Static::ClipContents
    592 ================
    593 */
    594 int idPhysics_Static::ClipContents( const idClipModel *model ) const {
    595 	if ( clipModel ) {
    596 		if ( model ) {
    597 			return gameLocal.clip.ContentsModel( clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1,
    598 				model->Handle(), model->GetOrigin(), model->GetAxis() );
    599 		} else {
    600 			return gameLocal.clip.Contents( clipModel->GetOrigin(), clipModel, clipModel->GetAxis(), -1, NULL );
    601 		}
    602 	}
    603 	return 0;
    604 }
    605 
    606 /*
    607 ================
    608 idPhysics_Static::DisableClip
    609 ================
    610 */
    611 void idPhysics_Static::DisableClip() {
    612 	if ( clipModel ) {
    613 		clipModel->Disable();
    614 	}
    615 }
    616 
    617 /*
    618 ================
    619 idPhysics_Static::EnableClip
    620 ================
    621 */
    622 void idPhysics_Static::EnableClip() {
    623 	if ( clipModel ) {
    624 		clipModel->Enable();
    625 	}
    626 }
    627 
    628 /*
    629 ================
    630 idPhysics_Static::UnlinkClip
    631 ================
    632 */
    633 void idPhysics_Static::UnlinkClip() {
    634 	if ( clipModel ) {
    635 		clipModel->Unlink();
    636 	}
    637 }
    638 
    639 /*
    640 ================
    641 idPhysics_Static::LinkClip
    642 ================
    643 */
    644 void idPhysics_Static::LinkClip() {
    645 	if ( clipModel ) {
    646 		clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
    647 	}
    648 }
    649 
    650 /*
    651 ================
    652 idPhysics_Static::EvaluateContacts
    653 ================
    654 */
    655 bool idPhysics_Static::EvaluateContacts() {
    656 	return false;
    657 }
    658 
    659 /*
    660 ================
    661 idPhysics_Static::GetNumContacts
    662 ================
    663 */
    664 int idPhysics_Static::GetNumContacts() const {
    665 	return 0;
    666 }
    667 
    668 /*
    669 ================
    670 idPhysics_Static::GetContact
    671 ================
    672 */
    673 const contactInfo_t &idPhysics_Static::GetContact( int num ) const {
    674 	static contactInfo_t info;
    675 	memset( &info, 0, sizeof( info ) );
    676 	return info;
    677 }
    678 
    679 /*
    680 ================
    681 idPhysics_Static::ClearContacts
    682 ================
    683 */
    684 void idPhysics_Static::ClearContacts() {
    685 }
    686 
    687 /*
    688 ================
    689 idPhysics_Static::AddContactEntity
    690 ================
    691 */
    692 void idPhysics_Static::AddContactEntity( idEntity *e ) {
    693 }
    694 
    695 /*
    696 ================
    697 idPhysics_Static::RemoveContactEntity
    698 ================
    699 */
    700 void idPhysics_Static::RemoveContactEntity( idEntity *e ) {
    701 }
    702 
    703 /*
    704 ================
    705 idPhysics_Static::HasGroundContacts
    706 ================
    707 */
    708 bool idPhysics_Static::HasGroundContacts() const {
    709 	return false;
    710 }
    711 
    712 /*
    713 ================
    714 idPhysics_Static::IsGroundEntity
    715 ================
    716 */
    717 bool idPhysics_Static::IsGroundEntity( int entityNum ) const {
    718 	return false;
    719 }
    720 
    721 /*
    722 ================
    723 idPhysics_Static::IsGroundClipModel
    724 ================
    725 */
    726 bool idPhysics_Static::IsGroundClipModel( int entityNum, int id ) const {
    727 	return false;
    728 }
    729 
    730 /*
    731 ================
    732 idPhysics_Static::SetPushed
    733 ================
    734 */
    735 void idPhysics_Static::SetPushed( int deltaTime ) {
    736 }
    737 
    738 /*
    739 ================
    740 idPhysics_Static::GetPushedLinearVelocity
    741 ================
    742 */
    743 const idVec3 &idPhysics_Static::GetPushedLinearVelocity( const int id ) const {
    744 	return vec3_origin;
    745 }
    746 
    747 /*
    748 ================
    749 idPhysics_Static::GetPushedAngularVelocity
    750 ================
    751 */
    752 const idVec3 &idPhysics_Static::GetPushedAngularVelocity( const int id ) const {
    753 	return vec3_origin;
    754 }
    755 
    756 /*
    757 ================
    758 idPhysics_Static::SetMaster
    759 ================
    760 */
    761 void idPhysics_Static::SetMaster( idEntity *master, const bool orientated ) {
    762 	idVec3 masterOrigin;
    763 	idMat3 masterAxis;
    764 
    765 	if ( master ) {
    766 		if ( !hasMaster ) {
    767 			// transform from world space to master space
    768 			self->GetMasterPosition( masterOrigin, masterAxis );
    769 			current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
    770 			if ( orientated ) {
    771 				current.localAxis = current.axis * masterAxis.Transpose();
    772 			} else {
    773 				current.localAxis = current.axis;
    774 			}
    775 			hasMaster = true;
    776 			isOrientated = orientated;
    777 		}
    778 	} else {
    779 		if ( hasMaster ) {
    780 			hasMaster = false;
    781 		}
    782 	}
    783 }
    784 
    785 /*
    786 ================
    787 idPhysics_Static::GetBlockingInfo
    788 ================
    789 */
    790 const trace_t *idPhysics_Static::GetBlockingInfo() const {
    791 	return NULL;
    792 }
    793 
    794 /*
    795 ================
    796 idPhysics_Static::GetBlockingEntity
    797 ================
    798 */
    799 idEntity *idPhysics_Static::GetBlockingEntity() const {
    800 	return NULL;
    801 }
    802 
    803 /*
    804 ================
    805 idPhysics_Static::GetLinearEndTime
    806 ================
    807 */
    808 int idPhysics_Static::GetLinearEndTime() const {
    809 	return 0;
    810 }
    811 
    812 /*
    813 ================
    814 idPhysics_Static::GetAngularEndTime
    815 ================
    816 */
    817 int idPhysics_Static::GetAngularEndTime() const {
    818 	return 0;
    819 }
    820 
    821 /*
    822 ================
    823 idPhysics_Static::WriteToSnapshot
    824 ================
    825 */
    826 void idPhysics_Static::WriteToSnapshot( idBitMsg &msg ) const {
    827 	idCQuat quat, localQuat;
    828 
    829 	quat = current.axis.ToCQuat();
    830 	localQuat = current.localAxis.ToCQuat();
    831 
    832 	msg.WriteFloat( current.origin[0] );
    833 	msg.WriteFloat( current.origin[1] );
    834 	msg.WriteFloat( current.origin[2] );
    835 	msg.WriteFloat( quat.x );
    836 	msg.WriteFloat( quat.y );
    837 	msg.WriteFloat( quat.z );
    838 	msg.WriteDeltaFloat( current.origin[0], current.localOrigin[0] );
    839 	msg.WriteDeltaFloat( current.origin[1], current.localOrigin[1] );
    840 	msg.WriteDeltaFloat( current.origin[2], current.localOrigin[2] );
    841 	msg.WriteDeltaFloat( quat.x, localQuat.x );
    842 	msg.WriteDeltaFloat( quat.y, localQuat.y );
    843 	msg.WriteDeltaFloat( quat.z, localQuat.z );
    844 }
    845 
    846 /*
    847 ================
    848 idPhysics_Base::ReadFromSnapshot
    849 ================
    850 */
    851 void idPhysics_Static::ReadFromSnapshot( const idBitMsg &msg ) {
    852 	idCQuat quat, localQuat;
    853 
    854 	previous = next;
    855 
    856 	next = ReadStaticInterpolatePStateFromSnapshot( msg );
    857 }
    858 
    859 /*
    860 ================
    861 ConvertInterpolateStateToPState
    862 ================
    863 */
    864 staticPState_s	ConvertInterpolateStateToPState( const staticInterpolatePState_t & interpolateState  ) {
    865 
    866 	staticPState_s state;
    867 	state.origin = interpolateState.origin;
    868 	state.localOrigin = interpolateState.localOrigin;
    869 	state.localAxis = interpolateState.localAxis.ToMat3();
    870 	state.axis = interpolateState.axis.ToMat3();
    871 
    872 	return state;
    873 }
    874 
    875 /*
    876 ================
    877 ConvertPStateToInterpolateState
    878 ================
    879 */
    880 staticInterpolatePState_t ConvertPStateToInterpolateState( const staticPState_t & state ) {
    881 
    882 	staticInterpolatePState_t interpolateState;
    883 	interpolateState.origin = state.origin;
    884 	interpolateState.localOrigin = state.localOrigin;
    885 	interpolateState.localAxis = state.localAxis.ToQuat();
    886 	interpolateState.axis = state.axis.ToQuat();
    887 
    888 	return interpolateState;
    889 }
    890 
    891 /*
    892 ================
    893 ReadStaticInterpolatePStateFromSnapshot
    894 ================
    895 */
    896 staticInterpolatePState_t ReadStaticInterpolatePStateFromSnapshot( const idBitMsg & msg ) { 
    897 	staticInterpolatePState_t state;
    898 
    899 	state.origin = ReadFloatArray< idVec3 >( msg );
    900 	const idCQuat cAxis = ReadFloatArray< idCQuat >( msg );
    901 	state.localOrigin = ReadDeltaFloatArray( msg, state.origin );
    902 	state.localAxis = ReadDeltaFloatArray( msg, cAxis ).ToQuat();
    903 
    904 	state.axis = cAxis.ToQuat();
    905 
    906 	return state;
    907 }
    908 
    909 /*
    910 ================
    911 InterpolateStaticPState
    912 ================
    913 */
    914 staticPState_t InterpolateStaticPState( const staticInterpolatePState_t & previous, const staticInterpolatePState_t & next, float fraction ) {
    915 	staticPState_t result;
    916 	
    917 	result.origin = Lerp( previous.origin, next.origin, fraction );
    918 	result.axis = idQuat().Slerp( previous.axis, next.axis, fraction ).ToMat3();
    919 
    920 	result.localOrigin = Lerp( previous.localOrigin, next.localOrigin, fraction );
    921 	result.localAxis = idQuat().Slerp( previous.localAxis, next.localAxis, fraction ).ToMat3();
    922 
    923 	return result;
    924 }