DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Physics_AF.cpp (201633B)


      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_AF )
     35 END_CLASS
     36 
     37 const float ERROR_REDUCTION					= 0.5f;
     38 const float ERROR_REDUCTION_MAX				= 256.0f;
     39 const float LIMIT_ERROR_REDUCTION			= 0.3f;
     40 const float LCP_EPSILON						= 1e-7f;
     41 const float LIMIT_LCP_EPSILON				= 1e-4f;
     42 const float CONTACT_LCP_EPSILON				= 1e-6f;
     43 const float CENTER_OF_MASS_EPSILON			= 1e-4f;
     44 const float NO_MOVE_TIME					= 1.0f;
     45 const float NO_MOVE_TRANSLATION_TOLERANCE	= 10.0f;
     46 const float NO_MOVE_ROTATION_TOLERANCE		= 10.0f;
     47 const float MIN_MOVE_TIME					= -1.0f;
     48 const float MAX_MOVE_TIME					= -1.0f;
     49 const float IMPULSE_THRESHOLD				= 500.0f;
     50 const float SUSPEND_LINEAR_VELOCITY			= 10.0f;
     51 const float SUSPEND_ANGULAR_VELOCITY		= 15.0f;
     52 const float SUSPEND_LINEAR_ACCELERATION		= 20.0f;
     53 const float SUSPEND_ANGULAR_ACCELERATION	= 30.0f;
     54 const idVec6 vec6_lcp_epsilon				= idVec6( LCP_EPSILON, LCP_EPSILON, LCP_EPSILON,
     55 													 LCP_EPSILON, LCP_EPSILON, LCP_EPSILON );
     56 
     57 #define AF_TIMINGS
     58 
     59 #ifdef AF_TIMINGS
     60 static int lastTimerReset = 0;
     61 static int numArticulatedFigures = 0;
     62 static idTimer timer_total, timer_pc, timer_ac, timer_collision, timer_lcp;
     63 #endif
     64 
     65 
     66 
     67 //===============================================================
     68 //
     69 //	idAFConstraint
     70 //
     71 //===============================================================
     72 
     73 /*
     74 ================
     75 idAFConstraint::idAFConstraint
     76 ================
     77 */
     78 idAFConstraint::idAFConstraint() {
     79 	type				= CONSTRAINT_INVALID;
     80 	name				= "noname";
     81 	body1				= NULL;
     82 	body2				= NULL;
     83 	physics				= NULL;
     84 
     85 	lo.Zero( 6 );
     86 	lo.SubVec6(0)		= -vec6_infinity;
     87 	hi.Zero( 6 );
     88 	hi.SubVec6(0)		= vec6_infinity;
     89 	e.SetSize( 6 );
     90 	e.SubVec6(0)		= vec6_lcp_epsilon;
     91 
     92 	boxConstraint		= NULL;
     93 	boxIndex[0]			= -1;
     94 	boxIndex[1]			= -1;
     95 	boxIndex[2]			= -1;
     96 	boxIndex[3]			= -1;
     97 	boxIndex[4]			= -1;
     98 	boxIndex[5]			= -1;
     99 
    100 	firstIndex			= 0;
    101 
    102 	memset( &fl, 0, sizeof( fl ) );
    103 }
    104 
    105 /*
    106 ================
    107 idAFConstraint::~idAFConstraint
    108 ================
    109 */
    110 idAFConstraint::~idAFConstraint() {
    111 }
    112 
    113 /*
    114 ================
    115 idAFConstraint::SetBody1
    116 ================
    117 */
    118 void idAFConstraint::SetBody1( idAFBody *body ) {
    119 	if ( body1 != body) {
    120 		body1 = body;
    121 		if ( physics ) {
    122 			physics->SetChanged();
    123 		}
    124 	}
    125 }
    126 
    127 /*
    128 ================
    129 idAFConstraint::SetBody2
    130 ================
    131 */
    132 void idAFConstraint::SetBody2( idAFBody *body ) {
    133 	if ( body2 != body ) {
    134 		body2 = body;
    135 		if ( physics ) {
    136 			physics->SetChanged();
    137 		}
    138 	}
    139 }
    140 
    141 /*
    142 ================
    143 idAFConstraint::GetMultiplier
    144 ================
    145 */
    146 const idVecX &idAFConstraint::GetMultiplier() {
    147 	return lm;
    148 }
    149 
    150 /*
    151 ================
    152 idAFConstraint::Evaluate
    153 ================
    154 */
    155 void idAFConstraint::Evaluate( float invTimeStep ) {
    156 	assert( 0 );
    157 }
    158 
    159 /*
    160 ================
    161 idAFConstraint::ApplyFriction
    162 ================
    163 */
    164 void idAFConstraint::ApplyFriction( float invTimeStep ) {
    165 }
    166 
    167 /*
    168 ================
    169 idAFConstraint::GetForce
    170 ================
    171 */
    172 void idAFConstraint::GetForce( idAFBody *body, idVec6 &force ) {
    173 	idVecX v;
    174 
    175 	v.SetData( 6, VECX_ALLOCA( 6 ) );
    176 	if ( body == body1 ) {
    177 		J1.TransposeMultiply( v, lm );
    178 	}
    179 	else if ( body == body2 ) {
    180 		J2.TransposeMultiply( v, lm );
    181 	}
    182 	else {
    183 		v.Zero();
    184 	}
    185 	force[0] = v[0]; force[1] = v[1]; force[2] = v[2]; force[3] = v[3]; force[4] = v[4]; force[5] = v[5];
    186 }
    187 
    188 /*
    189 ================
    190 idAFConstraint::Translate
    191 ================
    192 */
    193 void idAFConstraint::Translate( const idVec3 &translation ) {
    194 	assert( 0 );
    195 }
    196 
    197 /*
    198 ================
    199 idAFConstraint::Rotate
    200 ================
    201 */
    202 void idAFConstraint::Rotate( const idRotation &rotation ) {
    203 	assert( 0 );
    204 }
    205 
    206 /*
    207 ================
    208 idAFConstraint::GetCenter
    209 ================
    210 */
    211 void idAFConstraint::GetCenter( idVec3 &center ) {
    212 	center.Zero();
    213 }
    214 
    215 /*
    216 ================
    217 idAFConstraint::DebugDraw
    218 ================
    219 */
    220 void idAFConstraint::DebugDraw() {
    221 }
    222 
    223 /*
    224 ================
    225 idAFConstraint::InitSize
    226 ================
    227 */
    228 void idAFConstraint::InitSize( int size ) {
    229 	J1.Zero( size, 6 );
    230 	J2.Zero( size, 6 );
    231 	c1.Zero( size );
    232 	c2.Zero( size );
    233 	s.Zero( size );
    234 	lm.Zero( size );
    235 }
    236 
    237 /*
    238 ================
    239 idAFConstraint::Save
    240 ================
    241 */
    242 void idAFConstraint::Save( idSaveGame *saveFile ) const {
    243 	saveFile->WriteInt( type );
    244 }
    245 
    246 /*
    247 ================
    248 idAFConstraint::Restore
    249 ================
    250 */
    251 void idAFConstraint::Restore( idRestoreGame *saveFile ) {
    252 	constraintType_t t;
    253 	saveFile->ReadInt( (int &)t );
    254 	assert( t == type );
    255 }
    256 
    257 
    258 //===============================================================
    259 //
    260 //	idAFConstraint_Fixed
    261 //
    262 //===============================================================
    263 
    264 /*
    265 ================
    266 idAFConstraint_Fixed::idAFConstraint_Fixed
    267 ================
    268 */
    269 idAFConstraint_Fixed::idAFConstraint_Fixed( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
    270 	assert( body1 );
    271 	type = CONSTRAINT_FIXED;
    272 	this->name = name;
    273 	this->body1 = body1;
    274 	this->body2 = body2;
    275 	InitSize( 6 );
    276 	fl.allowPrimary = true;
    277 	fl.noCollision = true;
    278 
    279 	InitOffset();
    280 }
    281 
    282 /*
    283 ================
    284 idAFConstraint_Fixed::InitOffset
    285 ================
    286 */
    287 void idAFConstraint_Fixed::InitOffset() {
    288 	if ( body2 ) {
    289 		offset = ( body1->GetWorldOrigin() - body2->GetWorldOrigin() ) * body2->GetWorldAxis().Transpose();
    290 		relAxis = body1->GetWorldAxis() * body2->GetWorldAxis().Transpose();
    291 	}
    292 	else {
    293 		offset = body1->GetWorldOrigin();
    294 		relAxis = body1->GetWorldAxis();
    295 	}
    296 }
    297 
    298 /*
    299 ================
    300 idAFConstraint_Fixed::SetBody1
    301 ================
    302 */
    303 void idAFConstraint_Fixed::SetBody1( idAFBody *body ) {
    304 	if ( body1 != body) {
    305 		body1 = body;
    306 		InitOffset();
    307 		if ( physics ) {
    308 			physics->SetChanged();
    309 		}
    310 	}
    311 }
    312 
    313 /*
    314 ================
    315 idAFConstraint_Fixed::SetBody2
    316 ================
    317 */
    318 void idAFConstraint_Fixed::SetBody2( idAFBody *body ) {
    319 	if ( body2 != body ) {
    320 		body2 = body;
    321 		InitOffset();
    322 		if ( physics ) {
    323 			physics->SetChanged();
    324 		}
    325 	}
    326 }
    327 
    328 /*
    329 ================
    330 idAFConstraint_Fixed::Evaluate
    331 ================
    332 */
    333 void idAFConstraint_Fixed::Evaluate( float invTimeStep ) {
    334 	idVec3 ofs, a2;
    335 	idMat3 ax;
    336 	idRotation r;
    337 	idAFBody *master;
    338 
    339 	master = body2 ? body2 : physics->GetMasterBody();
    340 
    341 	if ( master ) {
    342 		a2 = offset * master->GetWorldAxis();
    343 		ofs = a2 + master->GetWorldOrigin();
    344 		ax = relAxis * master->GetWorldAxis();
    345 	}
    346 	else {
    347 		a2.Zero();
    348 		ofs = offset;
    349 		ax = relAxis;
    350 	}
    351 
    352 	J1.Set(	mat3_identity, mat3_zero,
    353 				mat3_zero, mat3_identity );
    354 
    355 	if ( body2 ) {
    356 		J2.Set(	-mat3_identity, SkewSymmetric( a2 ),
    357 					mat3_zero, -mat3_identity );
    358 	}
    359 	else {
    360 		J2.Zero( 6, 6 );
    361 	}
    362 
    363 	c1.SubVec3(0) = -( invTimeStep * ERROR_REDUCTION ) * ( ofs - body1->GetWorldOrigin() );
    364 	r = ( body1->GetWorldAxis().Transpose() * ax ).ToRotation();
    365 	c1.SubVec3(1) = -( invTimeStep * ERROR_REDUCTION ) * ( r.GetVec() * -(float) DEG2RAD( r.GetAngle() ) );
    366 
    367 	c1.Clamp( -ERROR_REDUCTION_MAX, ERROR_REDUCTION_MAX );
    368 }
    369 
    370 /*
    371 ================
    372 idAFConstraint_Fixed::ApplyFriction
    373 ================
    374 */
    375 void idAFConstraint_Fixed::ApplyFriction( float invTimeStep ) {
    376 	// no friction
    377 }
    378 
    379 /*
    380 ================
    381 idAFConstraint_Fixed::Translate
    382 ================
    383 */
    384 void idAFConstraint_Fixed::Translate( const idVec3 &translation ) {
    385 	if ( !body2 ) {
    386 		offset += translation;
    387 	}
    388 }
    389 
    390 /*
    391 ================
    392 idAFConstraint_Fixed::Rotate
    393 ================
    394 */
    395 void idAFConstraint_Fixed::Rotate( const idRotation &rotation ) {
    396 	if ( !body2 ) {
    397 		offset *= rotation;
    398 		relAxis *= rotation.ToMat3();
    399 	}
    400 }
    401 
    402 /*
    403 ================
    404 idAFConstraint_Fixed::GetCenter
    405 ================
    406 */
    407 void idAFConstraint_Fixed::GetCenter( idVec3 &center ) {
    408 	center = body1->GetWorldOrigin();
    409 }
    410 
    411 /*
    412 ================
    413 idAFConstraint_Fixed::DebugDraw
    414 ================
    415 */
    416 void idAFConstraint_Fixed::DebugDraw() {
    417 	idAFBody *master;
    418 
    419 	master = body2 ? body2 : physics->GetMasterBody();
    420 	if ( master ) {
    421 		gameRenderWorld->DebugLine( colorRed, body1->GetWorldOrigin(), master->GetWorldOrigin() );
    422 	}
    423 	else {
    424 		gameRenderWorld->DebugLine( colorRed, body1->GetWorldOrigin(), vec3_origin );
    425 	}
    426 }
    427 
    428 /*
    429 ================
    430 idAFConstraint_Fixed::Save
    431 ================
    432 */
    433 void idAFConstraint_Fixed::Save( idSaveGame *saveFile ) const {
    434 	idAFConstraint::Save( saveFile );
    435 	saveFile->WriteVec3( offset );
    436 	saveFile->WriteMat3( relAxis );
    437 }
    438 
    439 /*
    440 ================
    441 idAFConstraint_Fixed::Restore
    442 ================
    443 */
    444 void idAFConstraint_Fixed::Restore( idRestoreGame *saveFile ) {
    445 	idAFConstraint::Restore( saveFile );
    446 	saveFile->ReadVec3( offset );
    447 	saveFile->ReadMat3( relAxis );
    448 }
    449 
    450 
    451 //===============================================================
    452 //
    453 //	idAFConstraint_BallAndSocketJoint
    454 //
    455 //===============================================================
    456 
    457 /*
    458 ================
    459 idAFConstraint_BallAndSocketJoint::idAFConstraint_BallAndSocketJoint
    460 ================
    461 */
    462 idAFConstraint_BallAndSocketJoint::idAFConstraint_BallAndSocketJoint( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
    463 	assert( body1 );
    464 	type = CONSTRAINT_BALLANDSOCKETJOINT;
    465 	this->name = name;
    466 	this->body1 = body1;
    467 	this->body2 = body2;
    468 	InitSize( 3 );
    469 	coneLimit = NULL;
    470 	pyramidLimit = NULL;
    471 	friction = 0.0f;
    472 	fc = NULL;
    473 	fl.allowPrimary = true;
    474 	fl.noCollision = true;
    475 }
    476 
    477 /*
    478 ================
    479 idAFConstraint_BallAndSocketJoint::~idAFConstraint_BallAndSocketJoint
    480 ================
    481 */
    482 idAFConstraint_BallAndSocketJoint::~idAFConstraint_BallAndSocketJoint() {
    483 	if ( coneLimit ) {
    484 		delete coneLimit;
    485 	}
    486 	if ( pyramidLimit ) {
    487 		delete pyramidLimit;
    488 	}
    489 }
    490 
    491 /*
    492 ================
    493 idAFConstraint_BallAndSocketJoint::SetAnchor
    494 ================
    495 */
    496 void idAFConstraint_BallAndSocketJoint::SetAnchor( const idVec3 &worldPosition ) {
    497 
    498 	// get anchor relative to center of mass of body1
    499 	anchor1 = ( worldPosition - body1->GetWorldOrigin() ) * body1->GetWorldAxis().Transpose();
    500 	if ( body2 ) {
    501 		// get anchor relative to center of mass of body2
    502 		anchor2 = ( worldPosition - body2->GetWorldOrigin() ) * body2->GetWorldAxis().Transpose();
    503 	}
    504 	else {
    505 		anchor2 = worldPosition;
    506 	}
    507 
    508 	if ( coneLimit ) {
    509 		coneLimit->SetAnchor( anchor2 );
    510 	}
    511 	if ( pyramidLimit ) {
    512 		pyramidLimit->SetAnchor( anchor2 );
    513 	}
    514 }
    515 
    516 /*
    517 ================
    518 idAFConstraint_BallAndSocketJoint::GetAnchor
    519 ================
    520 */
    521 idVec3 idAFConstraint_BallAndSocketJoint::GetAnchor() const {
    522 	if ( body2 ) {
    523 		return body2->GetWorldOrigin() + body2->GetWorldAxis() * anchor2;
    524 	}
    525 	return anchor2;
    526 }
    527 
    528 /*
    529 ================
    530 idAFConstraint_BallAndSocketJoint::SetNoLimit
    531 ================
    532 */
    533 void idAFConstraint_BallAndSocketJoint::SetNoLimit() {
    534 	if ( coneLimit ) {
    535 		delete coneLimit;
    536 		coneLimit = NULL;
    537 	}
    538 	if ( pyramidLimit ) {
    539 		delete pyramidLimit;
    540 		pyramidLimit = NULL;
    541 	}
    542 }
    543 
    544 /*
    545 ================
    546 idAFConstraint_BallAndSocketJoint::SetConeLimit
    547 ================
    548 */
    549 void idAFConstraint_BallAndSocketJoint::SetConeLimit( const idVec3 &coneAxis, const float coneAngle, const idVec3 &body1Axis ) {
    550 	if ( pyramidLimit ) {
    551 		delete pyramidLimit;
    552 		pyramidLimit = NULL;
    553 	}
    554 	if ( !coneLimit ) {
    555 		coneLimit = new (TAG_PHYSICS_AF) idAFConstraint_ConeLimit;
    556 		coneLimit->SetPhysics( physics );
    557 	}
    558 	if ( body2 ) {
    559 		coneLimit->Setup( body1, body2, anchor2, coneAxis * body2->GetWorldAxis().Transpose(), coneAngle, body1Axis * body1->GetWorldAxis().Transpose() );
    560 	}
    561 	else {
    562 		coneLimit->Setup( body1, body2, anchor2, coneAxis, coneAngle, body1Axis * body1->GetWorldAxis().Transpose() );
    563 	}
    564 }
    565 
    566 /*
    567 ================
    568 idAFConstraint_BallAndSocketJoint::SetPyramidLimit
    569 ================
    570 */
    571 void idAFConstraint_BallAndSocketJoint::SetPyramidLimit( const idVec3 &pyramidAxis, const idVec3 &baseAxis,
    572 														const float angle1, const float angle2, const idVec3 &body1Axis ) {
    573 	if ( coneLimit ) {
    574 		delete coneLimit;
    575 		coneLimit = NULL;
    576 	}
    577 	if ( !pyramidLimit ) {
    578 		pyramidLimit = new (TAG_PHYSICS_AF) idAFConstraint_PyramidLimit;
    579 		pyramidLimit->SetPhysics( physics );
    580 	}
    581 	if ( body2 ) {
    582 		pyramidLimit->Setup( body1, body2, anchor2, pyramidAxis * body2->GetWorldAxis().Transpose(),
    583 									baseAxis * body2->GetWorldAxis().Transpose(), angle1, angle2,
    584 											body1Axis * body1->GetWorldAxis().Transpose() );
    585 	}
    586 	else {
    587 		pyramidLimit->Setup( body1, body2, anchor2, pyramidAxis, baseAxis, angle1, angle2,
    588 											body1Axis * body1->GetWorldAxis().Transpose() );
    589 	}
    590 }
    591 
    592 /*
    593 ================
    594 idAFConstraint_BallAndSocketJoint::SetLimitEpsilon
    595 ================
    596 */
    597 void idAFConstraint_BallAndSocketJoint::SetLimitEpsilon( const float e ) {
    598 	if ( coneLimit ) {
    599 		coneLimit->SetEpsilon( e );
    600 	}
    601 	if ( pyramidLimit ) {
    602 		pyramidLimit->SetEpsilon( e );
    603 	}
    604 }
    605 
    606 /*
    607 ================
    608 idAFConstraint_BallAndSocketJoint::GetFriction
    609 ================
    610 */
    611 float idAFConstraint_BallAndSocketJoint::GetFriction() const {
    612 	if ( af_forceFriction.GetFloat() > 0.0f ) {
    613 		return af_forceFriction.GetFloat();
    614 	}
    615 	return friction * physics->GetJointFrictionScale();
    616 }
    617 
    618 /*
    619 ================
    620 idAFConstraint_BallAndSocketJoint::Evaluate
    621 ================
    622 */
    623 void idAFConstraint_BallAndSocketJoint::Evaluate( float invTimeStep ) {
    624 	idVec3 a1, a2;
    625 	idAFBody *master;
    626 
    627 	master = body2 ? body2 : physics->GetMasterBody();
    628 
    629 	a1 = anchor1 * body1->GetWorldAxis();
    630 
    631 	if ( master ) {
    632 		a2 = anchor2 * master->GetWorldAxis();
    633 		c1.SubVec3(0) = -( invTimeStep * ERROR_REDUCTION ) * ( a2 + master->GetWorldOrigin() - ( a1 + body1->GetWorldOrigin() ) );
    634 	}
    635 	else {
    636 		c1.SubVec3(0) = -( invTimeStep * ERROR_REDUCTION ) * ( anchor2 - ( a1 + body1->GetWorldOrigin() ) );
    637 	}
    638 
    639 	c1.Clamp( -ERROR_REDUCTION_MAX, ERROR_REDUCTION_MAX );
    640 
    641 	J1.Set( mat3_identity, -SkewSymmetric( a1 ) );
    642 
    643 	if ( body2 ) {
    644 		J2.Set( -mat3_identity, SkewSymmetric( a2 ) );
    645 	}
    646 	else {
    647 		J2.Zero( 3, 6 );
    648 	}
    649 
    650 	if ( coneLimit ) {
    651 		coneLimit->Add( physics, invTimeStep );
    652 	}
    653 	else if ( pyramidLimit ) {
    654 		pyramidLimit->Add( physics, invTimeStep );
    655 	}
    656 }
    657 
    658 /*
    659 ================
    660 idAFConstraint_BallAndSocketJoint::ApplyFriction
    661 ================
    662 */
    663 void idAFConstraint_BallAndSocketJoint::ApplyFriction( float invTimeStep ) {
    664 	idVec3 angular;
    665 	float invMass, currentFriction;
    666 
    667 	currentFriction = GetFriction();
    668 
    669 	if ( currentFriction <= 0.0f ) {
    670 		return;
    671 	}
    672 
    673 	if ( af_useImpulseFriction.GetBool() || af_useJointImpulseFriction.GetBool() ) {
    674 
    675 		angular = body1->GetAngularVelocity();
    676 		invMass = body1->GetInverseMass();
    677 		if ( body2 ) {
    678 			angular -= body2->GetAngularVelocity();
    679 			invMass += body2->GetInverseMass();
    680 		}
    681 
    682 		angular *= currentFriction / invMass;
    683 
    684 		body1->SetAngularVelocity( body1->GetAngularVelocity() - angular * body1->GetInverseMass() );
    685 		if ( body2 ) {
    686 			body2->SetAngularVelocity( body2->GetAngularVelocity() + angular * body2->GetInverseMass() );
    687 		}
    688 	}
    689 	else {
    690 		if ( !fc ) {
    691 			fc = new (TAG_PHYSICS_AF) idAFConstraint_BallAndSocketJointFriction;
    692 			fc->Setup( this );
    693 		}
    694 
    695 		fc->Add( physics, invTimeStep );
    696 	}
    697 }
    698 
    699 /*
    700 ================
    701 idAFConstraint_BallAndSocketJoint::GetForce
    702 ================
    703 */
    704 void idAFConstraint_BallAndSocketJoint::GetForce( idAFBody *body, idVec6 &force ) {
    705 	idAFConstraint::GetForce( body, force );
    706 	// FIXME: add limit force
    707 }
    708 
    709 /*
    710 ================
    711 idAFConstraint_BallAndSocketJoint::Translate
    712 ================
    713 */
    714 void idAFConstraint_BallAndSocketJoint::Translate( const idVec3 &translation ) {
    715 	if ( !body2 ) {
    716 		anchor2 += translation;
    717 	}
    718 	if ( coneLimit ) {
    719 		coneLimit->Translate( translation );
    720 	}
    721 	else if ( pyramidLimit ) {
    722 		pyramidLimit->Translate( translation );
    723 	}
    724 }
    725 
    726 /*
    727 ================
    728 idAFConstraint_BallAndSocketJoint::Rotate
    729 ================
    730 */
    731 void idAFConstraint_BallAndSocketJoint::Rotate( const idRotation &rotation ) {
    732 	if ( !body2 ) {
    733 		anchor2 *= rotation;
    734 	}
    735 	if ( coneLimit ) {
    736 		coneLimit->Rotate( rotation );
    737 	}
    738 	else if ( pyramidLimit ) {
    739 		pyramidLimit->Rotate( rotation );
    740 	}
    741 }
    742 
    743 /*
    744 ================
    745 idAFConstraint_BallAndSocketJoint::GetCenter
    746 ================
    747 */
    748 void idAFConstraint_BallAndSocketJoint::GetCenter( idVec3 &center ) {
    749 	center = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
    750 }
    751 
    752 /*
    753 ================
    754 idAFConstraint_BallAndSocketJoint::DebugDraw
    755 ================
    756 */
    757 void idAFConstraint_BallAndSocketJoint::DebugDraw() {
    758 	idVec3 a1 = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
    759 	gameRenderWorld->DebugLine( colorBlue, a1 - idVec3( 5, 0, 0 ), a1 + idVec3( 5, 0, 0 ) );
    760 	gameRenderWorld->DebugLine( colorBlue, a1 - idVec3( 0, 5, 0 ), a1 + idVec3( 0, 5, 0 ) );
    761 	gameRenderWorld->DebugLine( colorBlue, a1 - idVec3( 0, 0, 5 ), a1 + idVec3( 0, 0, 5 ) );
    762 
    763 	if ( af_showLimits.GetBool() ) {
    764 		if ( coneLimit ) {
    765 			coneLimit->DebugDraw();
    766 		}
    767 		if ( pyramidLimit ) {
    768 			pyramidLimit->DebugDraw();
    769 		}
    770 	}
    771 }
    772 
    773 /*
    774 ================
    775 idAFConstraint_BallAndSocketJoint::Save
    776 ================
    777 */
    778 void idAFConstraint_BallAndSocketJoint::Save( idSaveGame *saveFile ) const {
    779 	idAFConstraint::Save( saveFile );
    780 	saveFile->WriteVec3( anchor1 );
    781 	saveFile->WriteVec3( anchor2 );
    782 	saveFile->WriteFloat( friction );
    783 	if ( coneLimit ) {
    784 		coneLimit->Save( saveFile );
    785 	}
    786 	if ( pyramidLimit ) {
    787 		pyramidLimit->Save( saveFile );
    788 	}
    789 }
    790 
    791 /*
    792 ================
    793 idAFConstraint_BallAndSocketJoint::Restore
    794 ================
    795 */
    796 void idAFConstraint_BallAndSocketJoint::Restore( idRestoreGame *saveFile ) {
    797 	idAFConstraint::Restore( saveFile );
    798 	saveFile->ReadVec3( anchor1 );
    799 	saveFile->ReadVec3( anchor2 );
    800 	saveFile->ReadFloat( friction );
    801 	if ( coneLimit ) {
    802 		coneLimit->Restore( saveFile );
    803 	}
    804 	if ( pyramidLimit ) {
    805 		pyramidLimit->Restore( saveFile );
    806 	}
    807 }
    808 
    809 
    810 //===============================================================
    811 //
    812 //	idAFConstraint_BallAndSocketJointFriction
    813 //
    814 //===============================================================
    815 
    816 /*
    817 ================
    818 idAFConstraint_BallAndSocketJointFriction::idAFConstraint_BallAndSocketJointFriction
    819 ================
    820 */
    821 idAFConstraint_BallAndSocketJointFriction::idAFConstraint_BallAndSocketJointFriction() {
    822 	type = CONSTRAINT_FRICTION;
    823 	name = "ballAndSocketJointFriction";
    824 	InitSize( 3 );
    825 	joint = NULL;
    826 	fl.allowPrimary = false;
    827 	fl.frameConstraint = true;
    828 }
    829 
    830 /*
    831 ================
    832 idAFConstraint_BallAndSocketJointFriction::Setup
    833 ================
    834 */
    835 void idAFConstraint_BallAndSocketJointFriction::Setup( idAFConstraint_BallAndSocketJoint *bsj ) {
    836 	this->joint = bsj;
    837 	body1 = bsj->GetBody1();
    838 	body2 = bsj->GetBody2();
    839 }
    840 
    841 /*
    842 ================
    843 idAFConstraint_BallAndSocketJointFriction::Evaluate
    844 ================
    845 */
    846 void idAFConstraint_BallAndSocketJointFriction::Evaluate( float invTimeStep ) {
    847 	// do nothing
    848 }
    849 
    850 /*
    851 ================
    852 idAFConstraint_BallAndSocketJointFriction::ApplyFriction
    853 ================
    854 */
    855 void idAFConstraint_BallAndSocketJointFriction::ApplyFriction( float invTimeStep ) {
    856 	// do nothing
    857 }
    858 
    859 /*
    860 ================
    861 idAFConstraint_BallAndSocketJointFriction::Add
    862 ================
    863 */
    864 bool idAFConstraint_BallAndSocketJointFriction::Add( idPhysics_AF *phys, float invTimeStep ) {
    865 	float f;
    866 
    867 	physics = phys;
    868 
    869 	f = joint->GetFriction() * joint->GetMultiplier().Length();
    870 	if ( f == 0.0f ) {
    871 		return false;
    872 	}
    873 
    874 	lo[0] = lo[1] = lo[2] = -f;
    875 	hi[0] = hi[1] = hi[2] = f;
    876 
    877 	J1.Zero( 3, 6 );
    878 	J1[0][3] = J1[1][4] = J1[2][5] = 1.0f;
    879 
    880 	if ( body2 ) {
    881 
    882 		J2.Zero( 3, 6 );
    883 		J2[0][3] = J2[1][4] = J2[2][5] = 1.0f;
    884 	}
    885 
    886 	physics->AddFrameConstraint( this );
    887 
    888 	return true;
    889 }
    890 
    891 /*
    892 ================
    893 idAFConstraint_BallAndSocketJointFriction::Translate
    894 ================
    895 */
    896 void idAFConstraint_BallAndSocketJointFriction::Translate( const idVec3 &translation ) {
    897 }
    898 
    899 /*
    900 ================
    901 idAFConstraint_BallAndSocketJointFriction::Rotate
    902 ================
    903 */
    904 void idAFConstraint_BallAndSocketJointFriction::Rotate( const idRotation &rotation ) {
    905 }
    906 
    907 
    908 //===============================================================
    909 //
    910 //	idAFConstraint_UniversalJoint
    911 //
    912 //===============================================================
    913 
    914 /*
    915 ================
    916 idAFConstraint_UniversalJoint::idAFConstraint_UniversalJoint
    917 ================
    918 */
    919 idAFConstraint_UniversalJoint::idAFConstraint_UniversalJoint( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
    920 	assert( body1 );
    921 	type = CONSTRAINT_UNIVERSALJOINT;
    922 	this->name = name;
    923 	this->body1 = body1;
    924 	this->body2 = body2;
    925 	InitSize( 4 );
    926 	coneLimit = NULL;
    927 	pyramidLimit = NULL;
    928 	friction = 0.0f;
    929 	fc = NULL;
    930 	fl.allowPrimary = true;
    931 	fl.noCollision = true;
    932 }
    933 
    934 /*
    935 ================
    936 idAFConstraint_UniversalJoint::~idAFConstraint_UniversalJoint
    937 ================
    938 */
    939 idAFConstraint_UniversalJoint::~idAFConstraint_UniversalJoint() {
    940 	if ( coneLimit ) {
    941 		delete coneLimit;
    942 	}
    943 	if ( pyramidLimit ) {
    944 		delete pyramidLimit;
    945 	}
    946 	if ( fc ) {
    947 		delete fc;
    948 	}
    949 }
    950 
    951 /*
    952 ================
    953 idAFConstraint_UniversalJoint::SetAnchor
    954 ================
    955 */
    956 void idAFConstraint_UniversalJoint::SetAnchor( const idVec3 &worldPosition ) {
    957 
    958 	// get anchor relative to center of mass of body1
    959 	anchor1 = ( worldPosition - body1->GetWorldOrigin() ) * body1->GetWorldAxis().Transpose();
    960 	if ( body2 ) {
    961 		// get anchor relative to center of mass of body2
    962 		anchor2 = ( worldPosition - body2->GetWorldOrigin() ) * body2->GetWorldAxis().Transpose();
    963 	}
    964 	else {
    965 		anchor2 = worldPosition;
    966 	}
    967 
    968 	if ( coneLimit ) {
    969 		coneLimit->SetAnchor( anchor2 );
    970 	}
    971 	if ( pyramidLimit ) {
    972 		pyramidLimit->SetAnchor( anchor2 );
    973 	}
    974 }
    975 
    976 /*
    977 ================
    978 idAFConstraint_UniversalJoint::GetAnchor
    979 ================
    980 */
    981 idVec3 idAFConstraint_UniversalJoint::GetAnchor() const {
    982 	if ( body2 ) {
    983 		return body2->GetWorldOrigin() + body2->GetWorldAxis() * anchor2;
    984 	}
    985 	return anchor2;
    986 }
    987 
    988 /*
    989 ================
    990 idAFConstraint_UniversalJoint::SetShafts
    991 ================
    992 */
    993 void idAFConstraint_UniversalJoint::SetShafts( const idVec3 &cardanShaft1, const idVec3 &cardanShaft2 ) {
    994 	idVec3 cardanAxis;
    995 	float l;
    996 
    997 	shaft1 = cardanShaft1;
    998 	l = shaft1.Normalize();
    999 	assert( l != 0.0f );
   1000 	shaft2 = cardanShaft2;
   1001 	l = shaft2.Normalize();
   1002 	assert( l != 0.0f );
   1003 
   1004 	// the cardan axis is a vector orthogonal to both cardan shafts
   1005 	cardanAxis = shaft1.Cross( shaft2 );
   1006 	if ( cardanAxis.Normalize() == 0.0f ) {
   1007 		idVec3 vecY;
   1008 		shaft1.OrthogonalBasis( cardanAxis, vecY );
   1009 		cardanAxis.Normalize();
   1010 	}
   1011 
   1012 	shaft1 *= body1->GetWorldAxis().Transpose();
   1013 	axis1 = cardanAxis * body1->GetWorldAxis().Transpose();
   1014 	if ( body2 ) {
   1015 		shaft2 *= body2->GetWorldAxis().Transpose();
   1016 		axis2 = cardanAxis * body2->GetWorldAxis().Transpose();
   1017 	}
   1018 	else {
   1019 		axis2 = cardanAxis;
   1020 	}
   1021 
   1022 	if ( coneLimit ) {
   1023 		coneLimit->SetBody1Axis( shaft1 );
   1024 	}
   1025 	if ( pyramidLimit ) {
   1026 		pyramidLimit->SetBody1Axis( shaft1 );
   1027 	}
   1028 }
   1029 
   1030 /*
   1031 ================
   1032 idAFConstraint_UniversalJoint::SetNoLimit
   1033 ================
   1034 */
   1035 void idAFConstraint_UniversalJoint::SetNoLimit() {
   1036 	if ( coneLimit ) {
   1037 		delete coneLimit;
   1038 		coneLimit = NULL;
   1039 	}
   1040 	if ( pyramidLimit ) {
   1041 		delete pyramidLimit;
   1042 		pyramidLimit = NULL;
   1043 	}
   1044 }
   1045 
   1046 /*
   1047 ================
   1048 idAFConstraint_UniversalJoint::SetConeLimit
   1049 ================
   1050 */
   1051 void idAFConstraint_UniversalJoint::SetConeLimit( const idVec3 &coneAxis, const float coneAngle ) {
   1052 	if ( pyramidLimit ) {
   1053 		delete pyramidLimit;
   1054 		pyramidLimit = NULL;
   1055 	}
   1056 	if ( !coneLimit ) {
   1057 		coneLimit = new (TAG_PHYSICS_AF) idAFConstraint_ConeLimit;
   1058 		coneLimit->SetPhysics( physics );
   1059 	}
   1060 	if ( body2 ) {
   1061 		coneLimit->Setup( body1, body2, anchor2, coneAxis * body2->GetWorldAxis().Transpose(), coneAngle, shaft1 );
   1062 	}
   1063 	else {
   1064 		coneLimit->Setup( body1, body2, anchor2, coneAxis, coneAngle, shaft1 );
   1065 	}
   1066 }
   1067 
   1068 /*
   1069 ================
   1070 idAFConstraint_UniversalJoint::SetPyramidLimit
   1071 ================
   1072 */
   1073 void idAFConstraint_UniversalJoint::SetPyramidLimit( const idVec3 &pyramidAxis, const idVec3 &baseAxis,
   1074 														const float angle1, const float angle2 ) {
   1075 	if ( coneLimit ) {
   1076 		delete coneLimit;
   1077 		coneLimit = NULL;
   1078 	}
   1079 	if ( !pyramidLimit ) {
   1080 		pyramidLimit = new (TAG_PHYSICS_AF) idAFConstraint_PyramidLimit;
   1081 		pyramidLimit->SetPhysics( physics );
   1082 	}
   1083 	if ( body2 ) {
   1084 		pyramidLimit->Setup( body1, body2, anchor2, pyramidAxis * body2->GetWorldAxis().Transpose(),
   1085 									baseAxis * body2->GetWorldAxis().Transpose(), angle1, angle2, shaft1 );
   1086 	}
   1087 	else {
   1088 		pyramidLimit->Setup( body1, body2, anchor2, pyramidAxis, baseAxis, angle1, angle2, shaft1 );
   1089 	}
   1090 }
   1091 
   1092 /*
   1093 ================
   1094 idAFConstraint_UniversalJoint::SetLimitEpsilon
   1095 ================
   1096 */
   1097 void idAFConstraint_UniversalJoint::SetLimitEpsilon( const float e ) {
   1098 	if ( coneLimit ) {
   1099 		coneLimit->SetEpsilon( e );
   1100 	}
   1101 	if ( pyramidLimit ) {
   1102 		pyramidLimit->SetEpsilon( e );
   1103 	}
   1104 }
   1105 
   1106 /*
   1107 ================
   1108 idAFConstraint_UniversalJoint::GetFriction
   1109 ================
   1110 */
   1111 float idAFConstraint_UniversalJoint::GetFriction() const {
   1112 	if ( af_forceFriction.GetFloat() > 0.0f ) {
   1113 		return af_forceFriction.GetFloat();
   1114 	}
   1115 	return friction * physics->GetJointFrictionScale();
   1116 }
   1117 
   1118 /*
   1119 ================
   1120 idAFConstraint_UniversalJoint::Evaluate
   1121 
   1122   NOTE: this joint is homokinetic
   1123 ================
   1124 */
   1125 void idAFConstraint_UniversalJoint::Evaluate( float invTimeStep ) {
   1126 	idVec3 a1, a2, s1, s2, d1, d2, v;
   1127 	idAFBody *master;
   1128 
   1129 	master = body2 ? body2 : physics->GetMasterBody();
   1130 
   1131 	a1 = anchor1 * body1->GetWorldAxis();
   1132 	s1 = shaft1 * body1->GetWorldAxis();
   1133 	d1 = s1.Cross( axis1 * body1->GetWorldAxis() );
   1134 
   1135 	if ( master ) {
   1136 		a2 = anchor2 * master->GetWorldAxis();
   1137 		s2 = shaft2 * master->GetWorldAxis();
   1138 		d2 = axis2 * master->GetWorldAxis();
   1139 		c1.SubVec3(0) = -( invTimeStep * ERROR_REDUCTION ) * ( a2 + master->GetWorldOrigin() - ( a1 + body1->GetWorldOrigin() ) );
   1140 	}
   1141 	else {
   1142 		a2 = anchor2;
   1143 		s2 = shaft2;
   1144 		d2 = axis2;
   1145 		c1.SubVec3(0) = -( invTimeStep * ERROR_REDUCTION ) * ( a2 - ( a1 + body1->GetWorldOrigin() ) );
   1146 	}
   1147 
   1148 	J1.Set(	mat3_identity,	-SkewSymmetric( a1 ),
   1149 				mat3_zero,		idMat3( s1[0], s1[1], s1[2],
   1150 										0.0f, 0.0f, 0.0f,
   1151 										0.0f, 0.0f, 0.0f ) );
   1152 	J1.SetSize( 4, 6 );
   1153 
   1154 	if ( body2 ) {
   1155 		J2.Set(	-mat3_identity,	SkewSymmetric( a2 ),
   1156 					mat3_zero,		idMat3( s2[0], s2[1], s2[2],
   1157 											0.0f, 0.0f, 0.0f,
   1158 											0.0f, 0.0f, 0.0f ) );
   1159 		J2.SetSize( 4, 6 );
   1160 	}
   1161 	else {
   1162 		J2.Zero( 4, 6 );
   1163 	}
   1164 
   1165 	v = s1.Cross( s2 );
   1166 	if ( v.Normalize() != 0.0f ) {
   1167 		idMat3 m1, m2;
   1168 
   1169 		m1[0] = s1;
   1170 		m1[1] = v;
   1171 		m1[2] = v.Cross( m1[0] );
   1172 
   1173 		m2[0] = -s2;
   1174 		m2[1] = v;
   1175 		m2[2] = v.Cross( m2[0] );
   1176 
   1177 		d2 *= m2.Transpose() * m1;
   1178 	}
   1179 
   1180 	c1[3] = -( invTimeStep * ERROR_REDUCTION ) * ( d1 * d2 );
   1181 
   1182 	c1.Clamp( -ERROR_REDUCTION_MAX, ERROR_REDUCTION_MAX );
   1183 
   1184 	if ( coneLimit ) {
   1185 		coneLimit->Add( physics, invTimeStep );
   1186 	}
   1187 	else if ( pyramidLimit ) {
   1188 		pyramidLimit->Add( physics, invTimeStep );
   1189 	}
   1190 }
   1191 
   1192 /*
   1193 ================
   1194 idAFConstraint_UniversalJoint::ApplyFriction
   1195 ================
   1196 */
   1197 void idAFConstraint_UniversalJoint::ApplyFriction( float invTimeStep ) {
   1198 	idVec3 angular;
   1199 	float invMass, currentFriction;
   1200 
   1201 	currentFriction = GetFriction();
   1202 
   1203 	if ( currentFriction <= 0.0f ) {
   1204 		return;
   1205 	}
   1206 
   1207 	if ( af_useImpulseFriction.GetBool() || af_useJointImpulseFriction.GetBool() ) {
   1208 
   1209 		angular = body1->GetAngularVelocity();
   1210 		invMass = body1->GetInverseMass();
   1211 		if ( body2 ) {
   1212 			angular -= body2->GetAngularVelocity();
   1213 			invMass += body2->GetInverseMass();
   1214 		}
   1215 
   1216 		angular *= currentFriction / invMass;
   1217 
   1218 		body1->SetAngularVelocity( body1->GetAngularVelocity() - angular * body1->GetInverseMass() );
   1219 		if ( body2 ) {
   1220 			body2->SetAngularVelocity( body2->GetAngularVelocity() + angular * body2->GetInverseMass() );
   1221 		}
   1222 	}
   1223 	else {
   1224 		if ( !fc ) {
   1225 			fc = new (TAG_PHYSICS_AF) idAFConstraint_UniversalJointFriction;
   1226 			fc->Setup( this );
   1227 		}
   1228 
   1229 		fc->Add( physics, invTimeStep );
   1230 	}
   1231 }
   1232 
   1233 /*
   1234 ================
   1235 idAFConstraint_UniversalJoint::GetForce
   1236 ================
   1237 */
   1238 void idAFConstraint_UniversalJoint::GetForce( idAFBody *body, idVec6 &force ) {
   1239 	idAFConstraint::GetForce( body, force );
   1240 	// FIXME: add limit force
   1241 }
   1242 
   1243 /*
   1244 ================
   1245 idAFConstraint_UniversalJoint::Translate
   1246 ================
   1247 */
   1248 void idAFConstraint_UniversalJoint::Translate( const idVec3 &translation ) {
   1249 	if ( !body2 ) {
   1250 		anchor2 += translation;
   1251 	}
   1252 	if ( coneLimit ) {
   1253 		coneLimit->Translate( translation );
   1254 	}
   1255 	else if ( pyramidLimit ) {
   1256 		pyramidLimit->Translate( translation );
   1257 	}
   1258 }
   1259 
   1260 /*
   1261 ================
   1262 idAFConstraint_UniversalJoint::Rotate
   1263 ================
   1264 */
   1265 void idAFConstraint_UniversalJoint::Rotate( const idRotation &rotation ) {
   1266 	if ( !body2 ) {
   1267 		anchor2 *= rotation;
   1268 		shaft2 *= rotation.ToMat3();
   1269 		axis2 *= rotation.ToMat3();
   1270 	}
   1271 	if ( coneLimit ) {
   1272 		coneLimit->Rotate( rotation );
   1273 	}
   1274 	else if ( pyramidLimit ) {
   1275 		pyramidLimit->Rotate( rotation );
   1276 	}
   1277 }
   1278 
   1279 /*
   1280 ================
   1281 idAFConstraint_UniversalJoint::GetCenter
   1282 ================
   1283 */
   1284 void idAFConstraint_UniversalJoint::GetCenter( idVec3 &center ) {
   1285 	center = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   1286 }
   1287 
   1288 /*
   1289 ================
   1290 idAFConstraint_UniversalJoint::DebugDraw
   1291 ================
   1292 */
   1293 void idAFConstraint_UniversalJoint::DebugDraw() {
   1294 	idVec3 a1, a2, s1, s2, d1, d2, v;
   1295 	idAFBody *master;
   1296 
   1297 	master = body2 ? body2 : physics->GetMasterBody();
   1298 
   1299 	a1 = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   1300 	s1 = shaft1 * body1->GetWorldAxis();
   1301 	d1 = axis1 * body1->GetWorldAxis();
   1302 
   1303 	if ( master ) {
   1304         a2 = master->GetWorldOrigin() + anchor2 * master->GetWorldAxis();
   1305 		s2 = shaft2 * master->GetWorldAxis();
   1306 		d2 = axis2 * master->GetWorldAxis();
   1307 	}
   1308 	else {
   1309         a2 = anchor2;
   1310 		s2 = shaft2;
   1311 		d2 = axis2;
   1312 	}
   1313 
   1314 	v = s1.Cross( s2 );
   1315 	if ( v.Normalize() != 0.0f ) {
   1316 		idMat3 m1, m2;
   1317 
   1318 		m1[0] = s1;
   1319 		m1[1] = v;
   1320 		m1[2] = v.Cross( m1[0] );
   1321 
   1322 		m2[0] = -s2;
   1323 		m2[1] = v;
   1324 		m2[2] = v.Cross( m2[0] );
   1325 
   1326 		d2 *= m2.Transpose() * m1;
   1327 	}
   1328 
   1329 	gameRenderWorld->DebugArrow( colorCyan, a1, a1 + s1 * 5.0f, 1.0f );
   1330 	gameRenderWorld->DebugArrow( colorBlue, a2, a2 + s2 * 5.0f, 1.0f );
   1331 	gameRenderWorld->DebugLine( colorGreen, a1, a1 + d1 * 5.0f );
   1332 	gameRenderWorld->DebugLine( colorGreen, a2, a2 + d2 * 5.0f );
   1333 
   1334 	if ( af_showLimits.GetBool() ) {
   1335 		if ( coneLimit ) {
   1336 			coneLimit->DebugDraw();
   1337 		}
   1338 		if ( pyramidLimit ) {
   1339 			pyramidLimit->DebugDraw();
   1340 		}
   1341 	}
   1342 }
   1343 
   1344 /*
   1345 ================
   1346 idAFConstraint_UniversalJoint::Save
   1347 ================
   1348 */
   1349 void idAFConstraint_UniversalJoint::Save( idSaveGame *saveFile ) const {
   1350 	idAFConstraint::Save( saveFile );
   1351 	saveFile->WriteVec3( anchor1 );
   1352 	saveFile->WriteVec3( anchor2 );
   1353 	saveFile->WriteVec3( shaft1 );
   1354 	saveFile->WriteVec3( shaft2 );
   1355 	saveFile->WriteVec3( axis1 );
   1356 	saveFile->WriteVec3( axis2 );
   1357 	saveFile->WriteFloat( friction );
   1358 	if ( coneLimit ) {
   1359 		coneLimit->Save( saveFile );
   1360 	}
   1361 	if ( pyramidLimit ) {
   1362 		pyramidLimit->Save( saveFile );
   1363 	}
   1364 }
   1365 
   1366 /*
   1367 ================
   1368 idAFConstraint_UniversalJoint::Restore
   1369 ================
   1370 */
   1371 void idAFConstraint_UniversalJoint::Restore( idRestoreGame *saveFile ) {
   1372 	idAFConstraint::Restore( saveFile );
   1373 	saveFile->ReadVec3( anchor1 );
   1374 	saveFile->ReadVec3( anchor2 );
   1375 	saveFile->ReadVec3( shaft1 );
   1376 	saveFile->ReadVec3( shaft2 );
   1377 	saveFile->ReadVec3( axis1 );
   1378 	saveFile->ReadVec3( axis2 );
   1379 	saveFile->ReadFloat( friction );
   1380 	if ( coneLimit ) {
   1381 		coneLimit->Restore( saveFile );
   1382 	}
   1383 	if ( pyramidLimit ) {
   1384 		pyramidLimit->Restore( saveFile );
   1385 	}
   1386 }
   1387 
   1388 
   1389 //===============================================================
   1390 //
   1391 //	idAFConstraint_UniversalJointFriction
   1392 //
   1393 //===============================================================
   1394 
   1395 /*
   1396 ================
   1397 idAFConstraint_UniversalJointFriction::idAFConstraint_UniversalJointFriction
   1398 ================
   1399 */
   1400 idAFConstraint_UniversalJointFriction::idAFConstraint_UniversalJointFriction() {
   1401 	type = CONSTRAINT_FRICTION;
   1402 	name = "universalJointFriction";
   1403 	InitSize( 2 );
   1404 	joint = NULL;
   1405 	fl.allowPrimary = false;
   1406 	fl.frameConstraint = true;
   1407 }
   1408 
   1409 /*
   1410 ================
   1411 idAFConstraint_UniversalJointFriction::Setup
   1412 ================
   1413 */
   1414 void idAFConstraint_UniversalJointFriction::Setup( idAFConstraint_UniversalJoint *uj ) {
   1415 	this->joint = uj;
   1416 	body1 = uj->GetBody1();
   1417 	body2 = uj->GetBody2();
   1418 }
   1419 
   1420 /*
   1421 ================
   1422 idAFConstraint_UniversalJointFriction::Evaluate
   1423 ================
   1424 */
   1425 void idAFConstraint_UniversalJointFriction::Evaluate( float invTimeStep ) {
   1426 	// do nothing
   1427 }
   1428 
   1429 /*
   1430 ================
   1431 idAFConstraint_UniversalJointFriction::ApplyFriction
   1432 ================
   1433 */
   1434 void idAFConstraint_UniversalJointFriction::ApplyFriction( float invTimeStep ) {
   1435 	// do nothing
   1436 }
   1437 
   1438 /*
   1439 ================
   1440 idAFConstraint_UniversalJointFriction::Add
   1441 ================
   1442 */
   1443 bool idAFConstraint_UniversalJointFriction::Add( idPhysics_AF *phys, float invTimeStep ) {
   1444 	idVec3 s1, s2, dir1, dir2;
   1445 	float f;
   1446 
   1447 	physics = phys;
   1448 
   1449 	f = joint->GetFriction() * joint->GetMultiplier().Length();
   1450 	if ( f == 0.0f ) {
   1451 		return false;
   1452 	}
   1453 
   1454 	lo[0] = lo[1] = -f;
   1455 	hi[0] = hi[1] = f;
   1456 
   1457 	joint->GetShafts( s1, s2 );
   1458 
   1459 	s1 *= body1->GetWorldAxis();
   1460 	s1.NormalVectors( dir1, dir2 );
   1461 
   1462 	J1.SetSize( 2, 6 );
   1463 	J1.SubVec6(0).SubVec3(0).Zero();
   1464 	J1.SubVec6(0).SubVec3(1) = dir1;
   1465 	J1.SubVec6(1).SubVec3(0).Zero();
   1466 	J1.SubVec6(1).SubVec3(1) = dir2;
   1467 
   1468 	if ( body2 ) {
   1469 
   1470 		J2.SetSize( 2, 6 );
   1471 		J2.SubVec6(0).SubVec3(0).Zero();
   1472 		J2.SubVec6(0).SubVec3(1) = -dir1;
   1473 		J2.SubVec6(1).SubVec3(0).Zero();
   1474 		J2.SubVec6(1).SubVec3(1) = -dir2;
   1475 	}
   1476 
   1477 	physics->AddFrameConstraint( this );
   1478 
   1479 	return true;
   1480 }
   1481 
   1482 /*
   1483 ================
   1484 idAFConstraint_UniversalJointFriction::Translate
   1485 ================
   1486 */
   1487 void idAFConstraint_UniversalJointFriction::Translate( const idVec3 &translation ) {
   1488 }
   1489 
   1490 /*
   1491 ================
   1492 idAFConstraint_UniversalJointFriction::Rotate
   1493 ================
   1494 */
   1495 void idAFConstraint_UniversalJointFriction::Rotate( const idRotation &rotation ) {
   1496 }
   1497 
   1498 
   1499 //===============================================================
   1500 //
   1501 //	idAFConstraint_CylindricalJoint
   1502 //
   1503 //===============================================================
   1504 
   1505 /*
   1506 ================
   1507 idAFConstraint_CylindricalJoint::idAFConstraint_CylindricalJoint
   1508 ================
   1509 */
   1510 idAFConstraint_CylindricalJoint::idAFConstraint_CylindricalJoint( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
   1511 	assert( 0 );	// FIXME: implement
   1512 }
   1513 
   1514 /*
   1515 ================
   1516 idAFConstraint_CylindricalJoint::Evaluate
   1517 ================
   1518 */
   1519 void idAFConstraint_CylindricalJoint::Evaluate( float invTimeStep ) {
   1520 	assert( 0 );	// FIXME: implement
   1521 }
   1522 
   1523 /*
   1524 ================
   1525 idAFConstraint_CylindricalJoint::ApplyFriction
   1526 ================
   1527 */
   1528 void idAFConstraint_CylindricalJoint::ApplyFriction( float invTimeStep ) {
   1529 	assert( 0 );	// FIXME: implement
   1530 }
   1531 
   1532 /*
   1533 ================
   1534 idAFConstraint_CylindricalJoint::Translate
   1535 ================
   1536 */
   1537 void idAFConstraint_CylindricalJoint::Translate( const idVec3 &translation ) {
   1538 	assert( 0 );	// FIXME: implement
   1539 }
   1540 
   1541 /*
   1542 ================
   1543 idAFConstraint_CylindricalJoint::Rotate
   1544 ================
   1545 */
   1546 void idAFConstraint_CylindricalJoint::Rotate( const idRotation &rotation ) {
   1547 	assert( 0 );	// FIXME: implement
   1548 }
   1549 
   1550 /*
   1551 ================
   1552 idAFConstraint_CylindricalJoint::DebugDraw
   1553 ================
   1554 */
   1555 void idAFConstraint_CylindricalJoint::DebugDraw() {
   1556 	assert( 0 );	// FIXME: implement
   1557 }
   1558 
   1559 
   1560 //===============================================================
   1561 //
   1562 //	idAFConstraint_Hinge
   1563 //
   1564 //===============================================================
   1565 
   1566 /*
   1567 ================
   1568 idAFConstraint_Hinge::idAFConstraint_Hinge
   1569 ================
   1570 */
   1571 idAFConstraint_Hinge::idAFConstraint_Hinge( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
   1572 	assert( body1 );
   1573 	type = CONSTRAINT_HINGE;
   1574 	this->name = name;
   1575 	this->body1 = body1;
   1576 	this->body2 = body2;
   1577 	InitSize( 5 );
   1578 	coneLimit = NULL;
   1579 	steering = NULL;
   1580 	friction = 0.0f;
   1581 	fc = NULL;
   1582 	fl.allowPrimary = true;
   1583 	fl.noCollision = true;
   1584 	initialAxis = body1->GetWorldAxis();
   1585 	if ( body2 ) {
   1586 		initialAxis *= body2->GetWorldAxis().Transpose();
   1587 	}
   1588 }
   1589 
   1590 /*
   1591 ================
   1592 idAFConstraint_Hinge::~idAFConstraint_Hinge
   1593 ================
   1594 */
   1595 idAFConstraint_Hinge::~idAFConstraint_Hinge() {
   1596 	if ( coneLimit ) {
   1597 		delete coneLimit;
   1598 	}
   1599 	if ( fc ) {
   1600 		delete fc;
   1601 	}
   1602 	if ( steering ) {
   1603 		delete steering;
   1604 	}
   1605 }
   1606 
   1607 /*
   1608 ================
   1609 idAFConstraint_Hinge::SetAnchor
   1610 ================
   1611 */
   1612 void idAFConstraint_Hinge::SetAnchor( const idVec3 &worldPosition ) {
   1613 	// get anchor relative to center of mass of body1
   1614 	anchor1 = ( worldPosition - body1->GetWorldOrigin() ) * body1->GetWorldAxis().Transpose();
   1615 	if ( body2 ) {
   1616 		// get anchor relative to center of mass of body2
   1617 		anchor2 = ( worldPosition - body2->GetWorldOrigin() ) * body2->GetWorldAxis().Transpose();
   1618 	}
   1619 	else {
   1620 		anchor2 = worldPosition;
   1621 	}
   1622 
   1623 	if ( coneLimit ) {
   1624 		coneLimit->SetAnchor( anchor2 );
   1625 	}
   1626 }
   1627 
   1628 /*
   1629 ================
   1630 idAFConstraint_Hinge::GetAnchor
   1631 ================
   1632 */
   1633 idVec3 idAFConstraint_Hinge::GetAnchor() const {
   1634 	if ( body2 ) {
   1635 		return body2->GetWorldOrigin() + body2->GetWorldAxis() * anchor2;
   1636 	}
   1637 	return anchor2;
   1638 }
   1639 
   1640 /*
   1641 ================
   1642 idAFConstraint_Hinge::SetAxis
   1643 ================
   1644 */
   1645 void idAFConstraint_Hinge::SetAxis( const idVec3 &axis ) {
   1646 	idVec3 normAxis;
   1647 
   1648 	normAxis = axis;
   1649 	normAxis.Normalize();
   1650 
   1651 	// get axis relative to body1
   1652 	axis1 = normAxis * body1->GetWorldAxis().Transpose();
   1653 	if ( body2 ) {
   1654 		// get axis relative to body2
   1655 		axis2 = normAxis * body2->GetWorldAxis().Transpose();
   1656 	}
   1657 	else {
   1658 		axis2 = normAxis;
   1659 	}
   1660 }
   1661 
   1662 /*
   1663 ================
   1664 idAFConstraint_Hinge::GetAxis
   1665 ================
   1666 */
   1667 idVec3 idAFConstraint_Hinge::GetAxis() const {
   1668 	if ( body2 ) {
   1669 		return axis2 * body2->GetWorldAxis();
   1670 	}
   1671 	return axis2;
   1672 }
   1673 
   1674 /*
   1675 ================
   1676 idAFConstraint_Hinge::SetNoLimit
   1677 ================
   1678 */
   1679 void idAFConstraint_Hinge::SetNoLimit() {
   1680 	if ( coneLimit ) {
   1681 		delete coneLimit;
   1682 		coneLimit = NULL;
   1683 	}
   1684 }
   1685 
   1686 /*
   1687 ================
   1688 idAFConstraint_Hinge::SetLimit
   1689 ================
   1690 */
   1691 void idAFConstraint_Hinge::SetLimit( const idVec3 &axis, const float angle, const idVec3 &body1Axis ) {
   1692 	if ( !coneLimit ) {
   1693 		coneLimit = new (TAG_PHYSICS_AF) idAFConstraint_ConeLimit;
   1694 		coneLimit->SetPhysics( physics );
   1695 	}
   1696 	if ( body2 ) {
   1697 		coneLimit->Setup( body1, body2, anchor2, axis * body2->GetWorldAxis().Transpose(), angle, body1Axis * body1->GetWorldAxis().Transpose() );
   1698 	}
   1699 	else {
   1700 		coneLimit->Setup( body1, body2, anchor2, axis, angle, body1Axis * body1->GetWorldAxis().Transpose() );
   1701 	}
   1702 }
   1703 
   1704 /*
   1705 ================
   1706 idAFConstraint_Hinge::SetLimitEpsilon
   1707 ================
   1708 */
   1709 void idAFConstraint_Hinge::SetLimitEpsilon( const float e ) {
   1710 	if ( coneLimit ) {
   1711 		coneLimit->SetEpsilon( e );
   1712 	}
   1713 }
   1714 
   1715 /*
   1716 ================
   1717 idAFConstraint_Hinge::GetFriction
   1718 ================
   1719 */
   1720 float idAFConstraint_Hinge::GetFriction() const {
   1721 	if ( af_forceFriction.GetFloat() > 0.0f ) {
   1722 		return af_forceFriction.GetFloat();
   1723 	}
   1724 	return friction * physics->GetJointFrictionScale();
   1725 }
   1726 
   1727 /*
   1728 ================
   1729 idAFConstraint_Hinge::GetAngle
   1730 ================
   1731 */
   1732 float idAFConstraint_Hinge::GetAngle() const {
   1733 	idMat3 axis;
   1734 	idRotation rotation;
   1735 	float angle;
   1736 
   1737 	axis = body1->GetWorldAxis() * body2->GetWorldAxis().Transpose() * initialAxis.Transpose();
   1738 	rotation = axis.ToRotation();
   1739 	angle = rotation.GetAngle();
   1740 	if ( rotation.GetVec() * axis1 < 0.0f ) {
   1741 		return -angle;
   1742 	}
   1743 	return angle;
   1744 }
   1745 
   1746 /*
   1747 ================
   1748 idAFConstraint_Hinge::SetSteerAngle
   1749 ================
   1750 */
   1751 void idAFConstraint_Hinge::SetSteerAngle( const float degrees ) {
   1752 	if ( coneLimit ) {
   1753 		delete coneLimit;
   1754 		coneLimit = NULL;
   1755 	}
   1756 	if ( !steering ) {
   1757 		steering = new (TAG_PHYSICS_AF) idAFConstraint_HingeSteering();
   1758 		steering->Setup( this );
   1759 	}
   1760 	steering->SetSteerAngle( degrees );
   1761 }
   1762 
   1763 /*
   1764 ================
   1765 idAFConstraint_Hinge::SetSteerSpeed
   1766 ================
   1767 */
   1768 void idAFConstraint_Hinge::SetSteerSpeed( const float speed ) {
   1769 	if ( steering ) {
   1770 		steering->SetSteerSpeed( speed );
   1771 	}
   1772 }
   1773 
   1774 /*
   1775 ================
   1776 idAFConstraint_Hinge::Evaluate
   1777 ================
   1778 */
   1779 void idAFConstraint_Hinge::Evaluate( float invTimeStep ) {
   1780 	idVec3 a1, a2;
   1781 	idVec3 x1, x2, cross;
   1782 	idVec3 vecX, vecY;
   1783 	idAFBody *master;
   1784 
   1785 	master = body2 ? body2 : physics->GetMasterBody();
   1786 
   1787 	x1 = axis1 * body1->GetWorldAxis();		// axis in body1 space
   1788 	x1.OrthogonalBasis( vecX, vecY );				// basis for axis in body1 space
   1789 
   1790 	a1 = anchor1 * body1->GetWorldAxis();	// anchor in body1 space
   1791 
   1792 	if ( master ) {
   1793 		a2 = anchor2 * master->GetWorldAxis();	// anchor in master space
   1794 		x2 = axis2 * master->GetWorldAxis();
   1795 		c1.SubVec3(0) = -( invTimeStep * ERROR_REDUCTION ) * ( a2 + master->GetWorldOrigin() - ( a1 + body1->GetWorldOrigin() ) );
   1796 	}
   1797 	else {
   1798 		a2 = anchor2;
   1799 		x2 = axis2;
   1800 		c1.SubVec3(0) = -( invTimeStep * ERROR_REDUCTION ) * ( a2 - ( a1 + body1->GetWorldOrigin() ) );
   1801 	}
   1802 
   1803 	J1.Set(	mat3_identity,	-SkewSymmetric( a1 ),
   1804 				mat3_zero,		idMat3(	vecX[0], vecX[1], vecX[2],
   1805 										vecY[0], vecY[1], vecY[2],
   1806 										0.0f, 0.0f, 0.0f ) );
   1807 	J1.SetSize( 5, 6 );
   1808 
   1809 	if ( body2 ) {
   1810 		J2.Set(	-mat3_identity,	SkewSymmetric( a2 ),
   1811 					mat3_zero,		idMat3(	-vecX[0], -vecX[1], -vecX[2],
   1812 											-vecY[0], -vecY[1], -vecY[2],
   1813 											0.0f, 0.0f, 0.0f ) );
   1814 		J2.SetSize( 5, 6 );
   1815 	}
   1816 	else {
   1817 		J2.Zero( 5, 6 );
   1818 	}
   1819 
   1820 	cross = x1.Cross( x2 );
   1821 
   1822 	c1[3] = -( invTimeStep * ERROR_REDUCTION ) * ( cross * vecX );
   1823 	c1[4] = -( invTimeStep * ERROR_REDUCTION ) * ( cross * vecY );
   1824 
   1825 	c1.Clamp( -ERROR_REDUCTION_MAX, ERROR_REDUCTION_MAX );
   1826 
   1827 	if ( steering ) {
   1828 		steering->Add( physics, invTimeStep );
   1829 	}
   1830 	else if ( coneLimit ) {
   1831 		coneLimit->Add( physics, invTimeStep );
   1832 	}
   1833 }
   1834 
   1835 /*
   1836 ================
   1837 idAFConstraint_Hinge::ApplyFriction
   1838 ================
   1839 */
   1840 void idAFConstraint_Hinge::ApplyFriction( float invTimeStep ) {
   1841 	idVec3 angular;
   1842 	float invMass, currentFriction;
   1843 
   1844 	currentFriction = GetFriction();
   1845 
   1846 	if ( currentFriction <= 0.0f ) {
   1847 		return;
   1848 	}
   1849 
   1850 	if ( af_useImpulseFriction.GetBool() || af_useJointImpulseFriction.GetBool() ) {
   1851 
   1852 		angular = body1->GetAngularVelocity();
   1853 		invMass = body1->GetInverseMass();
   1854 		if ( body2 ) {
   1855 			angular -= body2->GetAngularVelocity();
   1856 			invMass += body2->GetInverseMass();
   1857 		}
   1858 
   1859 		angular *= currentFriction / invMass;
   1860 
   1861 		body1->SetAngularVelocity( body1->GetAngularVelocity() - angular * body1->GetInverseMass() );
   1862 		if ( body2 ) {
   1863 			body2->SetAngularVelocity( body2->GetAngularVelocity() + angular * body2->GetInverseMass() );
   1864 		}
   1865 	}
   1866 	else {
   1867 		if ( !fc ) {
   1868 			fc = new (TAG_PHYSICS_AF) idAFConstraint_HingeFriction;
   1869 			fc->Setup( this );
   1870 		}
   1871 
   1872 		fc->Add( physics, invTimeStep );
   1873 	}
   1874 }
   1875 
   1876 /*
   1877 ================
   1878 idAFConstraint_Hinge::GetForce
   1879 ================
   1880 */
   1881 void idAFConstraint_Hinge::GetForce( idAFBody *body, idVec6 &force ) {
   1882 	idAFConstraint::GetForce( body, force );
   1883 	// FIXME: add limit force
   1884 }
   1885 
   1886 /*
   1887 ================
   1888 idAFConstraint_Hinge::Translate
   1889 ================
   1890 */
   1891 void idAFConstraint_Hinge::Translate( const idVec3 &translation ) {
   1892 	if ( !body2 ) {
   1893 		anchor2 += translation;
   1894 	}
   1895 	if ( coneLimit ) {
   1896 		coneLimit->Translate( translation );
   1897 	}
   1898 }
   1899 
   1900 /*
   1901 ================
   1902 idAFConstraint_Hinge::Rotate
   1903 ================
   1904 */
   1905 void idAFConstraint_Hinge::Rotate( const idRotation &rotation ) {
   1906 	if ( !body2 ) {
   1907 		anchor2 *= rotation;
   1908 		axis2 *= rotation.ToMat3();
   1909 	}
   1910 	if ( coneLimit ) {
   1911 		coneLimit->Rotate( rotation );
   1912 	}
   1913 }
   1914 
   1915 /*
   1916 ================
   1917 idAFConstraint_Hinge::GetCenter
   1918 ================
   1919 */
   1920 void idAFConstraint_Hinge::GetCenter( idVec3 &center ) {
   1921 	center = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   1922 }
   1923 
   1924 /*
   1925 ================
   1926 idAFConstraint_Hinge::DebugDraw
   1927 ================
   1928 */
   1929 void idAFConstraint_Hinge::DebugDraw() {
   1930 	idVec3 vecX, vecY;
   1931 	idVec3 a1 = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   1932 	idVec3 x1 = axis1 * body1->GetWorldAxis();
   1933 	x1.OrthogonalBasis( vecX, vecY );
   1934 
   1935 	gameRenderWorld->DebugArrow( colorBlue, a1 - 4.0f * x1, a1 + 4.0f * x1, 1 );
   1936 	gameRenderWorld->DebugLine( colorBlue, a1 - 2.0f * vecX, a1 + 2.0f * vecX );
   1937 	gameRenderWorld->DebugLine( colorBlue, a1 - 2.0f * vecY, a1 + 2.0f * vecY );
   1938 
   1939 	if ( af_showLimits.GetBool() ) {
   1940 		if ( coneLimit ) {
   1941 			coneLimit->DebugDraw();
   1942 		}
   1943 	}
   1944 }
   1945 
   1946 /*
   1947 ================
   1948 idAFConstraint_Hinge::Save
   1949 ================
   1950 */
   1951 void idAFConstraint_Hinge::Save( idSaveGame *saveFile ) const {
   1952 	idAFConstraint::Save( saveFile );
   1953 	saveFile->WriteVec3( anchor1 );
   1954 	saveFile->WriteVec3( anchor2 );
   1955 	saveFile->WriteVec3( axis1 );
   1956 	saveFile->WriteVec3( axis2 );
   1957 	saveFile->WriteMat3( initialAxis );
   1958 	saveFile->WriteFloat( friction );
   1959 	if ( coneLimit ) {
   1960 		saveFile->WriteBool( true );
   1961 		coneLimit->Save( saveFile );
   1962 	} else {
   1963 		saveFile->WriteBool( false );
   1964 	}
   1965 	if ( steering ) {
   1966 		saveFile->WriteBool( true );
   1967 		steering->Save( saveFile );
   1968 	} else {
   1969 		saveFile->WriteBool( false );
   1970 	}
   1971 	if ( fc ) {
   1972 		saveFile->WriteBool( true );
   1973 		fc->Save( saveFile );
   1974 	} else {
   1975 		saveFile->WriteBool( false );
   1976 	}
   1977 }
   1978 
   1979 /*
   1980 ================
   1981 idAFConstraint_Hinge::Restore
   1982 ================
   1983 */
   1984 void idAFConstraint_Hinge::Restore( idRestoreGame *saveFile ) {
   1985 	bool b;
   1986 	idAFConstraint::Restore( saveFile );
   1987 	saveFile->ReadVec3( anchor1 );
   1988 	saveFile->ReadVec3( anchor2 );
   1989 	saveFile->ReadVec3( axis1 );
   1990 	saveFile->ReadVec3( axis2 );
   1991 	saveFile->ReadMat3( initialAxis );
   1992 	saveFile->ReadFloat( friction );
   1993 
   1994 	saveFile->ReadBool( b );
   1995 	if ( b ) {
   1996 		if ( !coneLimit ) {
   1997 			coneLimit = new (TAG_PHYSICS_AF) idAFConstraint_ConeLimit;
   1998 		}
   1999 		coneLimit->SetPhysics( physics );
   2000 		coneLimit->Restore( saveFile );
   2001 	}
   2002 	saveFile->ReadBool( b );
   2003 	if ( b ) {
   2004 		if ( !steering ) {
   2005 			steering = new (TAG_PHYSICS_AF) idAFConstraint_HingeSteering;
   2006 		}
   2007 		steering->Setup( this );
   2008 		steering->Restore( saveFile );
   2009 	}
   2010 	saveFile->ReadBool( b );
   2011 	if ( b ) {
   2012 		if ( !fc ) {
   2013 			fc = new (TAG_PHYSICS_AF) idAFConstraint_HingeFriction;
   2014 		}
   2015 		fc->Setup( this );
   2016 		fc->Restore( saveFile );
   2017 	}
   2018 }
   2019 
   2020 
   2021 //===============================================================
   2022 //
   2023 //	idAFConstraint_HingeFriction
   2024 //
   2025 //===============================================================
   2026 
   2027 /*
   2028 ================
   2029 idAFConstraint_HingeFriction::idAFConstraint_HingeFriction
   2030 ================
   2031 */
   2032 idAFConstraint_HingeFriction::idAFConstraint_HingeFriction() {
   2033 	type = CONSTRAINT_FRICTION;
   2034 	name = "hingeFriction";
   2035 	InitSize( 1 );
   2036 	hinge = NULL;
   2037 	fl.allowPrimary = false;
   2038 	fl.frameConstraint = true;
   2039 }
   2040 
   2041 /*
   2042 ================
   2043 idAFConstraint_HingeFriction::Setup
   2044 ================
   2045 */
   2046 void idAFConstraint_HingeFriction::Setup( idAFConstraint_Hinge *h ) {
   2047 	this->hinge = h;
   2048 	body1 = h->GetBody1();
   2049 	body2 = h->GetBody2();
   2050 }
   2051 
   2052 /*
   2053 ================
   2054 idAFConstraint_HingeFriction::Evaluate
   2055 ================
   2056 */
   2057 void idAFConstraint_HingeFriction::Evaluate( float invTimeStep ) {
   2058 	// do nothing
   2059 }
   2060 
   2061 /*
   2062 ================
   2063 idAFConstraint_HingeFriction::ApplyFriction
   2064 ================
   2065 */
   2066 void idAFConstraint_HingeFriction::ApplyFriction( float invTimeStep ) {
   2067 	// do nothing
   2068 }
   2069 
   2070 /*
   2071 ================
   2072 idAFConstraint_HingeFriction::Add
   2073 ================
   2074 */
   2075 bool idAFConstraint_HingeFriction::Add( idPhysics_AF *phys, float invTimeStep ) {
   2076 	idVec3 a1, a2;
   2077 	float f;
   2078 
   2079 	physics = phys;
   2080 
   2081 	f = hinge->GetFriction() * hinge->GetMultiplier().Length();
   2082 	if ( f == 0.0f ) {
   2083 		return false;
   2084 	}
   2085 
   2086 	lo[0] = -f;
   2087 	hi[0] = f;
   2088 
   2089 	hinge->GetAxis( a1, a2 );
   2090 
   2091 	a1 *= body1->GetWorldAxis();
   2092 
   2093 	J1.SetSize( 1, 6 );
   2094 	J1.SubVec6(0).SubVec3(0).Zero();
   2095 	J1.SubVec6(0).SubVec3(1) = a1;
   2096 
   2097 	if ( body2 ) {
   2098 		a2 *= body2->GetWorldAxis();
   2099 
   2100 		J2.SetSize( 1, 6 );
   2101 		J2.SubVec6(0).SubVec3(0).Zero();
   2102 		J2.SubVec6(0).SubVec3(1) = -a2;
   2103 	}
   2104 
   2105 	physics->AddFrameConstraint( this );
   2106 
   2107 	return true;
   2108 }
   2109 
   2110 /*
   2111 ================
   2112 idAFConstraint_HingeFriction::Translate
   2113 ================
   2114 */
   2115 void idAFConstraint_HingeFriction::Translate( const idVec3 &translation ) {
   2116 }
   2117 
   2118 /*
   2119 ================
   2120 idAFConstraint_HingeFriction::Rotate
   2121 ================
   2122 */
   2123 void idAFConstraint_HingeFriction::Rotate( const idRotation &rotation ) {
   2124 }
   2125 
   2126 
   2127 //===============================================================
   2128 //
   2129 //	idAFConstraint_HingeSteering
   2130 //
   2131 //===============================================================
   2132 
   2133 /*
   2134 ================
   2135 idAFConstraint_HingeSteering::idAFConstraint_HingeSteering
   2136 ================
   2137 */
   2138 idAFConstraint_HingeSteering::idAFConstraint_HingeSteering() {
   2139 	type = CONSTRAINT_HINGESTEERING;
   2140 	name = "hingeFriction";
   2141 	InitSize( 1 );
   2142 	hinge = NULL;
   2143 	fl.allowPrimary = false;
   2144 	fl.frameConstraint = true;
   2145 	steerSpeed = 0.0f;
   2146 	epsilon = LCP_EPSILON;
   2147 }
   2148 
   2149 /*
   2150 ================
   2151 idAFConstraint_HingeSteering::Save
   2152 ================
   2153 */
   2154 void idAFConstraint_HingeSteering::Save( idSaveGame *saveFile ) const {
   2155 	saveFile->WriteFloat(steerAngle);
   2156 	saveFile->WriteFloat(steerSpeed);
   2157 	saveFile->WriteFloat(epsilon);
   2158 }
   2159 
   2160 /*
   2161 ================
   2162 idAFConstraint_HingeSteering::Restore
   2163 ================
   2164 */
   2165 void idAFConstraint_HingeSteering::Restore( idRestoreGame *saveFile ) {
   2166 	saveFile->ReadFloat(steerAngle);
   2167 	saveFile->ReadFloat(steerSpeed);
   2168 	saveFile->ReadFloat(epsilon);
   2169 }
   2170 
   2171 /*
   2172 ================
   2173 idAFConstraint_HingeSteering::Setup
   2174 ================
   2175 */
   2176 void idAFConstraint_HingeSteering::Setup( idAFConstraint_Hinge *h ) {
   2177 	this->hinge = h;
   2178 	body1 = h->GetBody1();
   2179 	body2 = h->GetBody2();
   2180 }
   2181 
   2182 /*
   2183 ================
   2184 idAFConstraint_HingeSteering::Evaluate
   2185 ================
   2186 */
   2187 void idAFConstraint_HingeSteering::Evaluate( float invTimeStep ) {
   2188 	// do nothing
   2189 }
   2190 
   2191 /*
   2192 ================
   2193 idAFConstraint_HingeSteering::ApplyFriction
   2194 ================
   2195 */
   2196 void idAFConstraint_HingeSteering::ApplyFriction( float invTimeStep ) {
   2197 	// do nothing
   2198 }
   2199 
   2200 /*
   2201 ================
   2202 idAFConstraint_HingeSteering::Add
   2203 ================
   2204 */
   2205 bool idAFConstraint_HingeSteering::Add( idPhysics_AF *phys, float invTimeStep ) {
   2206 	float angle, speed;
   2207 	idVec3 a1, a2;
   2208 
   2209 	physics = phys;
   2210 
   2211 	hinge->GetAxis( a1, a2 );
   2212 	angle = hinge->GetAngle();
   2213 
   2214 	a1 *= body1->GetWorldAxis();
   2215 
   2216 	J1.SetSize( 1, 6 );
   2217 	J1.SubVec6(0).SubVec3(0).Zero();
   2218 	J1.SubVec6(0).SubVec3(1) = a1;
   2219 
   2220 	if ( body2 ) {
   2221 		a2 *= body2->GetWorldAxis();
   2222 
   2223 		J2.SetSize( 1, 6 );
   2224 		J2.SubVec6(0).SubVec3(0).Zero();
   2225 		J2.SubVec6(0).SubVec3(1) = -a2;
   2226 	}
   2227 
   2228 	speed = steerAngle - angle;
   2229 	if ( steerSpeed != 0.0f ) {
   2230 		if ( speed > steerSpeed ) {
   2231 			speed = steerSpeed;
   2232 		}
   2233 		else if ( speed < -steerSpeed ) {
   2234 			speed = -steerSpeed;
   2235 		}
   2236 	}
   2237 
   2238 	c1[0] = DEG2RAD( speed ) * invTimeStep;
   2239 
   2240 	physics->AddFrameConstraint( this );
   2241 
   2242 	return true;
   2243 }
   2244 
   2245 /*
   2246 ================
   2247 idAFConstraint_HingeSteering::Translate
   2248 ================
   2249 */
   2250 void idAFConstraint_HingeSteering::Translate( const idVec3 &translation ) {
   2251 }
   2252 
   2253 /*
   2254 ================
   2255 idAFConstraint_HingeSteering::Rotate
   2256 ================
   2257 */
   2258 void idAFConstraint_HingeSteering::Rotate( const idRotation &rotation ) {
   2259 }
   2260 
   2261 
   2262 //===============================================================
   2263 //
   2264 //	idAFConstraint_Slider
   2265 //
   2266 //===============================================================
   2267 
   2268 /*
   2269 ================
   2270 idAFConstraint_Slider::idAFConstraint_Slider
   2271 ================
   2272 */
   2273 idAFConstraint_Slider::idAFConstraint_Slider( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
   2274 	assert( body1 );
   2275 	type = CONSTRAINT_SLIDER;
   2276 	this->name = name;
   2277 	this->body1 = body1;
   2278 	this->body2 = body2;
   2279 	InitSize( 5 );
   2280 	fl.allowPrimary = true;
   2281 	fl.noCollision = true;
   2282 
   2283 	if ( body2 ) {
   2284 		offset = ( body1->GetWorldOrigin() - body2->GetWorldOrigin() ) * body1->GetWorldAxis().Transpose();
   2285 		relAxis = body1->GetWorldAxis() * body2->GetWorldAxis().Transpose();
   2286 	}
   2287 	else {
   2288 		offset = body1->GetWorldOrigin();
   2289 		relAxis = body1->GetWorldAxis();
   2290 	}
   2291 }
   2292 
   2293 /*
   2294 ================
   2295 idAFConstraint_Slider::SetAxis
   2296 ================
   2297 */
   2298 void idAFConstraint_Slider::SetAxis( const idVec3 &ax ) {
   2299 	idVec3 normAxis;
   2300 
   2301 	// get normalized axis relative to body1
   2302 	normAxis = ax;
   2303 	normAxis.Normalize();
   2304 	if ( body2 ) {
   2305 		axis = normAxis * body2->GetWorldAxis().Transpose();
   2306 	}
   2307 	else {
   2308 		axis = normAxis;
   2309 	}
   2310 }
   2311 
   2312 /*
   2313 ================
   2314 idAFConstraint_Slider::Evaluate
   2315 ================
   2316 */
   2317 void idAFConstraint_Slider::Evaluate( float invTimeStep ) {
   2318 	idVec3 vecX, vecY, ofs;
   2319 	idRotation r;
   2320 	idAFBody *master;
   2321 
   2322 	master = body2 ? body2 : physics->GetMasterBody();
   2323 
   2324 	if ( master ) {
   2325 		(axis * master->GetWorldAxis()).OrthogonalBasis( vecX, vecY );
   2326 		ofs = master->GetWorldOrigin() + master->GetWorldAxis() * offset - body1->GetWorldOrigin();
   2327 		r = ( body1->GetWorldAxis().Transpose() * (relAxis * master->GetWorldAxis()) ).ToRotation();
   2328 	}
   2329 	else {
   2330 		axis.OrthogonalBasis( vecX, vecY );
   2331 		ofs = offset - body1->GetWorldOrigin();
   2332 		r = ( body1->GetWorldAxis().Transpose() * relAxis ).ToRotation();
   2333 	}
   2334 
   2335 	J1.Set(	mat3_zero, mat3_identity,
   2336 			idMat3( vecX, vecY, vec3_origin ), mat3_zero );
   2337 	J1.SetSize( 5, 6 );
   2338 
   2339 	if ( body2 ) {
   2340 
   2341 		J2.Set(	mat3_zero, -mat3_identity,
   2342 				idMat3( -vecX, -vecY, vec3_origin ), mat3_zero );
   2343 		J2.SetSize( 5, 6 );
   2344 	}
   2345 	else {
   2346 		J2.Zero( 5, 6 );
   2347 	}
   2348 
   2349 	c1.SubVec3(0) = -( invTimeStep * ERROR_REDUCTION ) * ( r.GetVec() * - (float) DEG2RAD( r.GetAngle() ) );
   2350 
   2351 	c1[3] = -( invTimeStep * ERROR_REDUCTION ) * ( vecX * ofs );
   2352 	c1[4] = -( invTimeStep * ERROR_REDUCTION ) * ( vecY * ofs );
   2353 
   2354 	c1.Clamp( -ERROR_REDUCTION_MAX, ERROR_REDUCTION_MAX );
   2355 }
   2356 
   2357 /*
   2358 ================
   2359 idAFConstraint_Slider::ApplyFriction
   2360 ================
   2361 */
   2362 void idAFConstraint_Slider::ApplyFriction( float invTimeStep ) {
   2363 	// no friction
   2364 }
   2365 
   2366 /*
   2367 ================
   2368 idAFConstraint_Slider::Translate
   2369 ================
   2370 */
   2371 void idAFConstraint_Slider::Translate( const idVec3 &translation ) {
   2372 	if ( !body2 ) {
   2373 		offset += translation;
   2374 	}
   2375 }
   2376 
   2377 /*
   2378 ================
   2379 idAFConstraint_Slider::Rotate
   2380 ================
   2381 */
   2382 void idAFConstraint_Slider::Rotate( const idRotation &rotation ) {
   2383 	if ( !body2 ) {
   2384 		offset *= rotation;
   2385 	}
   2386 }
   2387 
   2388 /*
   2389 ================
   2390 idAFConstraint_Slider::GetCenter
   2391 ================
   2392 */
   2393 void idAFConstraint_Slider::GetCenter( idVec3 &center ) {
   2394 	idAFBody *master;
   2395 
   2396 	master = body2 ? body2 : physics->GetMasterBody();
   2397 	if ( master ) {
   2398 		center = master->GetWorldOrigin() + master->GetWorldAxis() * offset - body1->GetWorldOrigin();
   2399 	}
   2400 	else {
   2401 		center = offset - body1->GetWorldOrigin();
   2402 	}
   2403 }
   2404 
   2405 /*
   2406 ================
   2407 idAFConstraint_Slider::DebugDraw
   2408 ================
   2409 */
   2410 void idAFConstraint_Slider::DebugDraw() {
   2411 	idVec3 ofs;
   2412 	idAFBody *master;
   2413 
   2414 	master = body2 ? body2 : physics->GetMasterBody();
   2415 	if ( master ) {
   2416 		ofs = master->GetWorldOrigin() + master->GetWorldAxis() * offset - body1->GetWorldOrigin();
   2417 	}
   2418 	else {
   2419 		ofs = offset - body1->GetWorldOrigin();
   2420 	}
   2421 	gameRenderWorld->DebugLine( colorGreen, ofs, ofs + axis * body1->GetWorldAxis() );
   2422 }
   2423 
   2424 /*
   2425 ================
   2426 idAFConstraint_Slider::Save
   2427 ================
   2428 */
   2429 void idAFConstraint_Slider::Save( idSaveGame *saveFile ) const {
   2430 	idAFConstraint::Save( saveFile );
   2431 	saveFile->WriteVec3( axis );
   2432 	saveFile->WriteVec3( offset );
   2433 	saveFile->WriteMat3( relAxis );
   2434 }
   2435 
   2436 /*
   2437 ================
   2438 idAFConstraint_Slider::Restore
   2439 ================
   2440 */
   2441 void idAFConstraint_Slider::Restore( idRestoreGame *saveFile ) {
   2442 	idAFConstraint::Restore( saveFile );
   2443 	saveFile->ReadVec3( axis );
   2444 	saveFile->ReadVec3( offset );
   2445 	saveFile->ReadMat3( relAxis );
   2446 }
   2447 
   2448 
   2449 //===============================================================
   2450 //
   2451 //	idAFConstraint_Line
   2452 //
   2453 //===============================================================
   2454 
   2455 /*
   2456 ================
   2457 idAFConstraint_Line::idAFConstraint_Line
   2458 ================
   2459 */
   2460 idAFConstraint_Line::idAFConstraint_Line( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
   2461 	assert( 0 );	// FIXME: implement
   2462 }
   2463 
   2464 /*
   2465 ================
   2466 idAFConstraint_Line::Evaluate
   2467 ================
   2468 */
   2469 void idAFConstraint_Line::Evaluate( float invTimeStep ) {
   2470 	assert( 0 );	// FIXME: implement
   2471 }
   2472 
   2473 /*
   2474 ================
   2475 idAFConstraint_Line::ApplyFriction
   2476 ================
   2477 */
   2478 void idAFConstraint_Line::ApplyFriction( float invTimeStep ) {
   2479 	assert( 0 );	// FIXME: implement
   2480 }
   2481 
   2482 /*
   2483 ================
   2484 idAFConstraint_Line::Translate
   2485 ================
   2486 */
   2487 void idAFConstraint_Line::Translate( const idVec3 &translation ) {
   2488 	assert( 0 );	// FIXME: implement
   2489 }
   2490 
   2491 /*
   2492 ================
   2493 idAFConstraint_Line::Rotate
   2494 ================
   2495 */
   2496 void idAFConstraint_Line::Rotate( const idRotation &rotation ) {
   2497 	assert( 0 );	// FIXME: implement
   2498 }
   2499 
   2500 /*
   2501 ================
   2502 idAFConstraint_Line::DebugDraw
   2503 ================
   2504 */
   2505 void idAFConstraint_Line::DebugDraw() {
   2506 	assert( 0 );	// FIXME: implement
   2507 }
   2508 
   2509 
   2510 //===============================================================
   2511 //
   2512 //	idAFConstraint_Plane
   2513 //
   2514 //===============================================================
   2515 
   2516 /*
   2517 ================
   2518 idAFConstraint_Plane::idAFConstraint_Plane
   2519 ================
   2520 */
   2521 idAFConstraint_Plane::idAFConstraint_Plane( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
   2522 	assert( body1 );
   2523 	type = CONSTRAINT_PLANE;
   2524 	this->name = name;
   2525 	this->body1 = body1;
   2526 	this->body2 = body2;
   2527 	InitSize( 1 );
   2528 	fl.allowPrimary = true;
   2529 	fl.noCollision = true;
   2530 }
   2531 
   2532 /*
   2533 ================
   2534 idAFConstraint_Plane::SetPlane
   2535 ================
   2536 */
   2537 void idAFConstraint_Plane::SetPlane( const idVec3 &normal, const idVec3 &anchor ) {
   2538 	// get anchor relative to center of mass of body1
   2539 	anchor1 = ( anchor - body1->GetWorldOrigin() ) * body1->GetWorldAxis().Transpose();
   2540 	if ( body2 ) {
   2541 		// get anchor relative to center of mass of body2
   2542 		anchor2 = ( anchor - body2->GetWorldOrigin() ) * body2->GetWorldAxis().Transpose();
   2543 		planeNormal = normal * body2->GetWorldAxis().Transpose();
   2544 	}
   2545 	else {
   2546 		anchor2 = anchor;
   2547 		planeNormal = normal;
   2548 	}
   2549 }
   2550 
   2551 /*
   2552 ================
   2553 idAFConstraint_Plane::Evaluate
   2554 ================
   2555 */
   2556 void idAFConstraint_Plane::Evaluate( float invTimeStep ) {
   2557 	idVec3 a1, a2, normal, p;
   2558 	idVec6 v;
   2559 	idAFBody *master;
   2560 
   2561 	master = body2 ? body2 : physics->GetMasterBody();
   2562 
   2563 	a1 = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   2564 	if ( master ) {
   2565 		a2 = master->GetWorldOrigin() + anchor2 * master->GetWorldAxis();
   2566 		normal = planeNormal * master->GetWorldAxis();
   2567 	}
   2568 	else {
   2569 		a2 = anchor2;
   2570 		normal = planeNormal;
   2571 	}
   2572 
   2573 	p = a1 - body1->GetWorldOrigin();
   2574 	v.SubVec3(0) = normal;
   2575 	v.SubVec3(1) = p.Cross( normal );
   2576 	J1.Set( 1, 6, v.ToFloatPtr() );
   2577 
   2578 	if ( body2 ) {
   2579 		p = a1 - body2->GetWorldOrigin();
   2580 		v.SubVec3(0) = -normal;
   2581 		v.SubVec3(1) = p.Cross( -normal );
   2582 		J2.Set( 1, 6, v.ToFloatPtr() );
   2583 	}
   2584 
   2585 	c1[0] = -( invTimeStep * ERROR_REDUCTION ) * (a1 * normal - a2 * normal);
   2586 
   2587 	c1.Clamp( -ERROR_REDUCTION_MAX, ERROR_REDUCTION_MAX );
   2588 }
   2589 
   2590 /*
   2591 ================
   2592 idAFConstraint_Plane::ApplyFriction
   2593 ================
   2594 */
   2595 void idAFConstraint_Plane::ApplyFriction( float invTimeStep ) {
   2596 	// no friction
   2597 }
   2598 
   2599 /*
   2600 ================
   2601 idAFConstraint_Plane::Translate
   2602 ================
   2603 */
   2604 void idAFConstraint_Plane::Translate( const idVec3 &translation ) {
   2605 	if ( !body2 ) {
   2606 		anchor2 += translation;
   2607 	}
   2608 }
   2609 
   2610 /*
   2611 ================
   2612 idAFConstraint_Plane::Rotate
   2613 ================
   2614 */
   2615 void idAFConstraint_Plane::Rotate( const idRotation &rotation ) {
   2616 	if ( !body2 ) {
   2617 		anchor2 *= rotation;
   2618 		planeNormal *= rotation.ToMat3();
   2619 	}
   2620 }
   2621 
   2622 /*
   2623 ================
   2624 idAFConstraint_Plane::DebugDraw
   2625 ================
   2626 */
   2627 void idAFConstraint_Plane::DebugDraw() {
   2628 	idVec3 a1, normal, right, up;
   2629 	idAFBody *master;
   2630 
   2631 	master = body2 ? body2 : physics->GetMasterBody();
   2632 
   2633 	a1 = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   2634 	if ( master ) {
   2635 		normal = planeNormal * master->GetWorldAxis();
   2636 	}
   2637 	else {
   2638 		normal = planeNormal;
   2639 	}
   2640 	normal.NormalVectors( right, up );
   2641 	normal *= 4.0f;
   2642 	right *= 4.0f;
   2643 	up *= 4.0f;
   2644 
   2645 	gameRenderWorld->DebugLine( colorCyan, a1 - right, a1 + right );
   2646 	gameRenderWorld->DebugLine( colorCyan, a1 - up, a1 + up );
   2647 	gameRenderWorld->DebugArrow( colorCyan, a1, a1 + normal, 1 );
   2648 }
   2649 
   2650 /*
   2651 ================
   2652 idAFConstraint_Plane::Save
   2653 ================
   2654 */
   2655 void idAFConstraint_Plane::Save( idSaveGame *saveFile ) const {
   2656 	idAFConstraint::Save( saveFile );
   2657 	saveFile->WriteVec3( anchor1 );
   2658 	saveFile->WriteVec3( anchor2 );
   2659 	saveFile->WriteVec3( planeNormal );
   2660 }
   2661 
   2662 /*
   2663 ================
   2664 idAFConstraint_Plane::Restore
   2665 ================
   2666 */
   2667 void idAFConstraint_Plane::Restore( idRestoreGame *saveFile ) {
   2668 	idAFConstraint::Restore( saveFile );
   2669 	saveFile->ReadVec3( anchor1 );
   2670 	saveFile->ReadVec3( anchor2 );
   2671 	saveFile->ReadVec3( planeNormal );
   2672 }
   2673 
   2674 
   2675 //===============================================================
   2676 //
   2677 //	idAFConstraint_Spring
   2678 //
   2679 //===============================================================
   2680 
   2681 /*
   2682 ================
   2683 idAFConstraint_Spring::idAFConstraint_Spring
   2684 ================
   2685 */
   2686 idAFConstraint_Spring::idAFConstraint_Spring( const idStr &name, idAFBody *body1, idAFBody *body2 ) {
   2687 	assert( body1 );
   2688 	type = CONSTRAINT_SPRING;
   2689 	this->name = name;
   2690 	this->body1 = body1;
   2691 	this->body2 = body2;
   2692 	InitSize( 1 );
   2693 	fl.allowPrimary = false;
   2694 	kstretch = kcompress = damping = 1.0f;
   2695 	minLength = maxLength = restLength = 0.0f;
   2696 }
   2697 
   2698 /*
   2699 ================
   2700 idAFConstraint_Spring::SetAnchor
   2701 ================
   2702 */
   2703 void idAFConstraint_Spring::SetAnchor( const idVec3 &worldAnchor1, const idVec3 &worldAnchor2 ) {
   2704 	// get anchor relative to center of mass of body1
   2705 	anchor1 = ( worldAnchor1 - body1->GetWorldOrigin() ) * body1->GetWorldAxis().Transpose();
   2706 	if ( body2 ) {
   2707 		// get anchor relative to center of mass of body2
   2708 		anchor2 = ( worldAnchor2 - body2->GetWorldOrigin() ) * body2->GetWorldAxis().Transpose();
   2709 	}
   2710 	else {
   2711 		anchor2 = worldAnchor2;
   2712 	}
   2713 }
   2714 
   2715 /*
   2716 ================
   2717 idAFConstraint_Spring::SetSpring
   2718 ================
   2719 */
   2720 void idAFConstraint_Spring::SetSpring( const float stretch, const float compress, const float damping, const float restLength ) {
   2721 	assert( stretch >= 0.0f && compress >= 0.0f && restLength >= 0.0f );
   2722 	this->kstretch = stretch;
   2723 	this->kcompress = compress;
   2724 	this->damping = damping;
   2725 	this->restLength = restLength;
   2726 }
   2727 
   2728 /*
   2729 ================
   2730 idAFConstraint_Spring::SetLimit
   2731 ================
   2732 */
   2733 void idAFConstraint_Spring::SetLimit( const float minLength, const float maxLength ) {
   2734 	assert( minLength >= 0.0f && maxLength >= 0.0f && maxLength >= minLength );
   2735 	this->minLength = minLength;
   2736 	this->maxLength = maxLength;
   2737 }
   2738 
   2739 /*
   2740 ================
   2741 idAFConstraint_Spring::Evaluate
   2742 ================
   2743 */
   2744 void idAFConstraint_Spring::Evaluate( float invTimeStep ) {
   2745 	idVec3 a1, a2, velocity1, velocity2, force;
   2746 	idVec6 v1, v2;
   2747 	float d, dampingForce, length, error;
   2748 	bool limit;
   2749 	idAFBody *master;
   2750 
   2751 	master = body2 ? body2 : physics->GetMasterBody();
   2752 
   2753 	a1 = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   2754 	velocity1 = body1->GetPointVelocity( a1 );
   2755 
   2756 	if ( master ) {
   2757 		a2 = master->GetWorldOrigin() + anchor2 * master->GetWorldAxis();
   2758 		velocity2 = master->GetPointVelocity( a2 );
   2759 	}
   2760 	else {
   2761 		a2 = anchor2;
   2762 		velocity2.Zero();
   2763 	}
   2764 
   2765 	force = a2 - a1;
   2766 	d = force * force;
   2767 	if ( d != 0.0f ) {
   2768 		dampingForce = damping * idMath::Fabs( (velocity2 - velocity1) * force ) / d;
   2769 	}
   2770 	else {
   2771 		dampingForce = 0.0f;
   2772 	}
   2773 	length = force.Normalize();
   2774 
   2775 	if ( length > restLength ) {
   2776 		if ( kstretch > 0.0f ) {
   2777 			idVec3 springForce = force * ( Square( length - restLength ) * kstretch - dampingForce );
   2778 			body1->AddForce( a1, springForce );
   2779 			if ( master ) {
   2780 				master->AddForce( a2, -springForce );
   2781 			}
   2782 		}
   2783 	}
   2784 	else {
   2785 		if ( kcompress > 0.0f ) {
   2786 			idVec3 springForce = force * -( Square( restLength - length ) * kcompress - dampingForce );
   2787 			body1->AddForce( a1, springForce );
   2788 			if ( master ) {
   2789 				master->AddForce( a2, -springForce );
   2790 			}
   2791 		}
   2792 	}
   2793 
   2794 	// check for spring limits
   2795 	if ( length < minLength ) {
   2796 		force = -force;
   2797 		error = minLength - length;
   2798 		limit = true;
   2799 	}
   2800 	else if ( maxLength > 0.0f && length > maxLength ) {
   2801 		error = length - maxLength;
   2802 		limit = true;
   2803 	}
   2804 	else {
   2805 		error = 0.0f;
   2806 		limit = false;
   2807 	}
   2808 
   2809 	if ( limit ) {
   2810 		a1 -= body1->GetWorldOrigin();
   2811 		v1.SubVec3(0) = force;
   2812 		v1.SubVec3(1) = a1.Cross( force );
   2813 		J1.Set( 1, 6, v1.ToFloatPtr() );
   2814 		if ( body2 ) {
   2815 			a2 -= body2->GetWorldOrigin();
   2816 			v2.SubVec3(0) = -force;
   2817 			v2.SubVec3(1) = a2.Cross( -force );
   2818 			J2.Set( 1, 6, v2.ToFloatPtr() );
   2819 		}
   2820 		c1[0] = -( invTimeStep * ERROR_REDUCTION ) * error;
   2821 		lo[0] = 0.0f;
   2822 	}
   2823 	else {
   2824 		J1.Zero( 0, 0 );
   2825 		J2.Zero( 0, 0 );
   2826 	}
   2827 
   2828 	c1.Clamp( -ERROR_REDUCTION_MAX, ERROR_REDUCTION_MAX );
   2829 }
   2830 
   2831 /*
   2832 ================
   2833 idAFConstraint_Spring::ApplyFriction
   2834 ================
   2835 */
   2836 void idAFConstraint_Spring::ApplyFriction( float invTimeStep ) {
   2837 	// no friction
   2838 }
   2839 
   2840 /*
   2841 ================
   2842 idAFConstraint_Spring::Translate
   2843 ================
   2844 */
   2845 void idAFConstraint_Spring::Translate( const idVec3 &translation ) {
   2846 	if ( !body2 ) {
   2847 		anchor2 += translation;
   2848 	}
   2849 }
   2850 
   2851 /*
   2852 ================
   2853 idAFConstraint_Spring::Rotate
   2854 ================
   2855 */
   2856 void idAFConstraint_Spring::Rotate( const idRotation &rotation ) {
   2857 	if ( !body2 ) {
   2858 		anchor2 *= rotation;
   2859 	}
   2860 }
   2861 
   2862 /*
   2863 ================
   2864 idAFConstraint_Spring::GetCenter
   2865 ================
   2866 */
   2867 void idAFConstraint_Spring::GetCenter( idVec3 &center ) {
   2868 	idAFBody *master;
   2869 	idVec3 a1, a2;
   2870 
   2871 	master = body2 ? body2 : physics->GetMasterBody();
   2872 	a1 = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   2873 	if ( master ) {
   2874 		a2 = master->GetWorldOrigin() + anchor2 * master->GetWorldAxis();
   2875 	}
   2876 	else {
   2877 		a2 = anchor2;
   2878 	}
   2879 	center = ( a1 + a2 ) * 0.5f;
   2880 }
   2881 
   2882 /*
   2883 ================
   2884 idAFConstraint_Spring::DebugDraw
   2885 ================
   2886 */
   2887 void idAFConstraint_Spring::DebugDraw() {
   2888 	idAFBody *master;
   2889 	float length;
   2890 	idVec3 a1, a2, dir, mid, p;
   2891 
   2892 	master = body2 ? body2 : physics->GetMasterBody();
   2893 	a1 = body1->GetWorldOrigin() + anchor1 * body1->GetWorldAxis();
   2894 	if ( master ) {
   2895 		a2 = master->GetWorldOrigin() + anchor2 * master->GetWorldAxis();
   2896 	}
   2897 	else {
   2898 		a2 = anchor2;
   2899 	}
   2900 	dir = a2 - a1;
   2901 	mid = a1 + 0.5f * dir;
   2902 	length = dir.Normalize();
   2903 
   2904 	// draw spring
   2905 	gameRenderWorld->DebugLine( colorGreen, a1, a2 );
   2906 
   2907 	// draw rest length
   2908 	p = restLength * 0.5f * dir;
   2909 	gameRenderWorld->DebugCircle( colorWhite, mid + p, dir, 1.0f, 10 );
   2910 	gameRenderWorld->DebugCircle( colorWhite, mid - p, dir, 1.0f, 10 );
   2911 	if ( restLength > length ) {
   2912 		gameRenderWorld->DebugLine( colorWhite, a2, mid + p );
   2913 		gameRenderWorld->DebugLine( colorWhite, a1, mid - p );
   2914 	}
   2915 
   2916 	if ( minLength > 0.0f ) {
   2917 		// draw min length
   2918 		gameRenderWorld->DebugCircle( colorBlue, mid + minLength * 0.5f * dir, dir, 2.0f, 10 );
   2919 		gameRenderWorld->DebugCircle( colorBlue, mid - minLength * 0.5f * dir, dir, 2.0f, 10 );
   2920 	}
   2921 
   2922 	if ( maxLength > 0.0f ) {
   2923 		// draw max length
   2924 		gameRenderWorld->DebugCircle( colorRed, mid + maxLength * 0.5f * dir, dir, 2.0f, 10 );
   2925 		gameRenderWorld->DebugCircle( colorRed, mid - maxLength * 0.5f * dir, dir, 2.0f, 10 );
   2926 	}
   2927 }
   2928 
   2929 /*
   2930 ================
   2931 idAFConstraint_Spring::Save
   2932 ================
   2933 */
   2934 void idAFConstraint_Spring::Save( idSaveGame *saveFile ) const {
   2935 	idAFConstraint::Save( saveFile );
   2936 	saveFile->WriteVec3( anchor1 );
   2937 	saveFile->WriteVec3( anchor2 );
   2938 	saveFile->WriteFloat( kstretch );
   2939 	saveFile->WriteFloat( kcompress );
   2940 	saveFile->WriteFloat( damping );
   2941 	saveFile->WriteFloat( restLength );
   2942 	saveFile->WriteFloat( minLength );
   2943 	saveFile->WriteFloat( maxLength );
   2944 }
   2945 
   2946 /*
   2947 ================
   2948 idAFConstraint_Spring::Restore
   2949 ================
   2950 */
   2951 void idAFConstraint_Spring::Restore( idRestoreGame *saveFile ) {
   2952 	idAFConstraint::Restore( saveFile );
   2953 	saveFile->ReadVec3( anchor1 );
   2954 	saveFile->ReadVec3( anchor2 );
   2955 	saveFile->ReadFloat( kstretch );
   2956 	saveFile->ReadFloat( kcompress );
   2957 	saveFile->ReadFloat( damping );
   2958 	saveFile->ReadFloat( restLength );
   2959 	saveFile->ReadFloat( minLength );
   2960 	saveFile->ReadFloat( maxLength );
   2961 }
   2962 
   2963 
   2964 //===============================================================
   2965 //
   2966 //	idAFConstraint_Contact
   2967 //
   2968 //===============================================================
   2969 
   2970 /*
   2971 ================
   2972 idAFConstraint_Contact::idAFConstraint_Contact
   2973 ================
   2974 */
   2975 idAFConstraint_Contact::idAFConstraint_Contact() {
   2976 	name = "contact";
   2977 	type = CONSTRAINT_CONTACT;
   2978 	InitSize( 1 );
   2979 	fc = NULL;
   2980 	fl.allowPrimary = false;
   2981 	fl.frameConstraint = true;
   2982 }
   2983 
   2984 /*
   2985 ================
   2986 idAFConstraint_Contact::~idAFConstraint_Contact
   2987 ================
   2988 */
   2989 idAFConstraint_Contact::~idAFConstraint_Contact() {
   2990 	if ( fc ) {
   2991 		delete fc;
   2992 	}
   2993 }
   2994 
   2995 /*
   2996 ================
   2997 idAFConstraint_Contact::Setup
   2998 ================
   2999 */
   3000 void idAFConstraint_Contact::Setup( idAFBody *b1, idAFBody *b2, contactInfo_t &c ) {
   3001 	idVec3 p;
   3002 	idVec6 v;
   3003 	float vel;
   3004 	float minBounceVelocity = 2.0f;
   3005 
   3006 	assert( b1 );
   3007 
   3008 	body1 = b1;
   3009 	body2 = b2;
   3010 	contact = c;
   3011 
   3012 	p = c.point - body1->GetWorldOrigin();
   3013 	v.SubVec3(0) = c.normal;
   3014 	v.SubVec3(1) = p.Cross( c.normal );
   3015 	J1.Set( 1, 6, v.ToFloatPtr() );
   3016 	vel = v.SubVec3(0) * body1->GetLinearVelocity() + v.SubVec3(1) * body1->GetAngularVelocity();
   3017 
   3018 	if ( body2 ) {
   3019 		p = c.point - body2->GetWorldOrigin();
   3020 		v.SubVec3(0) = -c.normal;
   3021 		v.SubVec3(1) = p.Cross( -c.normal );
   3022 		J2.Set( 1, 6, v.ToFloatPtr() );
   3023 		vel += v.SubVec3(0) * body2->GetLinearVelocity() + v.SubVec3(1) * body2->GetAngularVelocity();
   3024 		c2[0] = 0.0f;
   3025 	}
   3026 
   3027 	if ( body1->GetBouncyness() > 0.0f && -vel > minBounceVelocity ) {
   3028 		c1[0] = body1->GetBouncyness() * vel;
   3029 	}
   3030 	else {
   3031 		c1[0] = 0.0f;
   3032 	}
   3033 
   3034 	e[0] = CONTACT_LCP_EPSILON;
   3035 	lo[0] = 0.0f;
   3036 	hi[0] = idMath::INFINITY;
   3037 	boxConstraint = NULL;
   3038 	boxIndex[0] = -1;
   3039 }
   3040 
   3041 /*
   3042 ================
   3043 idAFConstraint_Contact::Evaluate
   3044 ================
   3045 */
   3046 void idAFConstraint_Contact::Evaluate( float invTimeStep ) {
   3047 	// do nothing
   3048 }
   3049 
   3050 /*
   3051 ================
   3052 idAFConstraint_Contact::ApplyFriction
   3053 ================
   3054 */
   3055 void idAFConstraint_Contact::ApplyFriction( float invTimeStep ) {
   3056 	idVec3 r, velocity, normal, dir1, dir2;
   3057 	float friction, magnitude, forceNumerator, forceDenominator;
   3058 	idVecX impulse, dv;
   3059 
   3060 	if ( !body1 ) {
   3061 		return;
   3062 	}
   3063 	friction = body1->GetContactFriction();
   3064 	if ( body2 && body2->GetContactFriction() < friction ) {
   3065 		friction = body2->GetContactFriction();
   3066 	}
   3067 
   3068 	friction *= physics->GetContactFrictionScale();
   3069 
   3070 	if ( friction <= 0.0f ) {
   3071 		return;
   3072 	}
   3073 
   3074 	// seperate friction per contact is silly but it's fast and often looks close enough
   3075 	if ( af_useImpulseFriction.GetBool() ) {
   3076 
   3077 		impulse.SetData( 6, VECX_ALLOCA( 6 ) );
   3078 		dv.SetData( 6, VECX_ALLOCA( 6 ) );
   3079 
   3080 		// calculate velocity in the contact plane
   3081 		r = contact.point - body1->GetWorldOrigin();
   3082 		velocity = body1->GetLinearVelocity() + body1->GetAngularVelocity().Cross( r );
   3083 		velocity -= contact.normal * velocity * contact.normal;
   3084 
   3085 		// get normalized direction of friction and magnitude of velocity
   3086 		normal = -velocity;
   3087 		magnitude = normal.Normalize();
   3088 
   3089 		forceNumerator = friction * magnitude;
   3090 		forceDenominator = body1->GetInverseMass() + ( ( body1->GetInverseWorldInertia() * r.Cross( normal ) ).Cross( r ) * normal );
   3091 		impulse.SubVec3(0) = (forceNumerator / forceDenominator) * normal;
   3092 		impulse.SubVec3(1) = r.Cross( impulse.SubVec3(0) );
   3093 		body1->InverseWorldSpatialInertiaMultiply( dv, impulse.ToFloatPtr() );
   3094 
   3095 		// modify velocity with friction force
   3096 		body1->SetLinearVelocity( body1->GetLinearVelocity() + dv.SubVec3(0) );
   3097 		body1->SetAngularVelocity( body1->GetAngularVelocity() + dv.SubVec3(1) );
   3098 	}
   3099 	else {
   3100 
   3101 		if ( !fc ) {
   3102 			fc = new (TAG_PHYSICS_AF) idAFConstraint_ContactFriction;
   3103 		}
   3104 		// call setup each frame because contact constraints are re-used for different bodies
   3105 		fc->Setup( this );
   3106 		fc->Add( physics, invTimeStep );
   3107 	}
   3108 }
   3109 
   3110 /*
   3111 ================
   3112 idAFConstraint_Contact::Translate
   3113 ================
   3114 */
   3115 void idAFConstraint_Contact::Translate( const idVec3 &translation ) {
   3116 	assert( 0 );	// contact should never be translated
   3117 }
   3118 
   3119 /*
   3120 ================
   3121 idAFConstraint_Contact::Rotate
   3122 ================
   3123 */
   3124 void idAFConstraint_Contact::Rotate( const idRotation &rotation ) {
   3125 	assert( 0 );	// contact should never be rotated
   3126 }
   3127 
   3128 /*
   3129 ================
   3130 idAFConstraint_Contact::GetCenter
   3131 ================
   3132 */
   3133 void idAFConstraint_Contact::GetCenter( idVec3 &center ) {
   3134 	center = contact.point;
   3135 }
   3136 
   3137 /*
   3138 ================
   3139 idAFConstraint_Contact::DebugDraw
   3140 ================
   3141 */
   3142 void idAFConstraint_Contact::DebugDraw() {
   3143 	idVec3 x, y;
   3144 	contact.normal.NormalVectors( x, y );
   3145 	gameRenderWorld->DebugLine( colorWhite, contact.point, contact.point + 6.0f * contact.normal );
   3146 	gameRenderWorld->DebugLine( colorWhite, contact.point - 2.0f * x, contact.point + 2.0f * x );
   3147 	gameRenderWorld->DebugLine( colorWhite, contact.point - 2.0f * y, contact.point + 2.0f * y );
   3148 }
   3149 
   3150 
   3151 //===============================================================
   3152 //
   3153 //	idAFConstraint_ContactFriction
   3154 //
   3155 //===============================================================
   3156 
   3157 /*
   3158 ================
   3159 idAFConstraint_ContactFriction::idAFConstraint_ContactFriction
   3160 ================
   3161 */
   3162 idAFConstraint_ContactFriction::idAFConstraint_ContactFriction() {
   3163 	type = CONSTRAINT_FRICTION;
   3164 	name = "contactFriction";
   3165 	InitSize( 2 );
   3166 	cc = NULL;
   3167 	fl.allowPrimary = false;
   3168 	fl.frameConstraint = true;
   3169 }
   3170 
   3171 /*
   3172 ================
   3173 idAFConstraint_ContactFriction::Setup
   3174 ================
   3175 */
   3176 void idAFConstraint_ContactFriction::Setup( idAFConstraint_Contact *cc ) {
   3177 	this->cc = cc;
   3178 	body1 = cc->GetBody1();
   3179 	body2 = cc->GetBody2();
   3180 }
   3181 
   3182 /*
   3183 ================
   3184 idAFConstraint_ContactFriction::Evaluate
   3185 ================
   3186 */
   3187 void idAFConstraint_ContactFriction::Evaluate( float invTimeStep ) {
   3188 	// do nothing
   3189 }
   3190 
   3191 /*
   3192 ================
   3193 idAFConstraint_ContactFriction::ApplyFriction
   3194 ================
   3195 */
   3196 void idAFConstraint_ContactFriction::ApplyFriction( float invTimeStep ) {
   3197 	// do nothing
   3198 }
   3199 
   3200 /*
   3201 ================
   3202 idAFConstraint_ContactFriction::Add
   3203 ================
   3204 */
   3205 bool idAFConstraint_ContactFriction::Add( idPhysics_AF *phys, float invTimeStep ) {
   3206 	idVec3 r, dir1, dir2;
   3207 	float friction;
   3208 	int newRow;
   3209 
   3210 	physics = phys;
   3211 
   3212 	friction = body1->GetContactFriction() * physics->GetContactFrictionScale();
   3213 
   3214 	// if the body only has friction in one direction
   3215 	if ( body1->GetFrictionDirection( dir1 ) ) {
   3216 		// project the friction direction into the contact plane
   3217 		dir1 -= dir1 * cc->GetContact().normal * dir1;
   3218 		dir1.Normalize();
   3219 
   3220 		r = cc->GetContact().point - body1->GetWorldOrigin();
   3221 
   3222 		J1.SetSize( 1, 6 );
   3223 		J1.SubVec6(0).SubVec3(0) = dir1;
   3224 		J1.SubVec6(0).SubVec3(1) = r.Cross( dir1 );
   3225 		c1.SetSize( 1 );
   3226 		c1[0] = 0.0f;
   3227 
   3228 		if ( body2 ) {
   3229 			r = cc->GetContact().point - body2->GetWorldOrigin();
   3230 
   3231 			J2.SetSize( 1, 6 );
   3232 			J2.SubVec6(0).SubVec3(0) = -dir1;
   3233 			J2.SubVec6(0).SubVec3(1) = r.Cross( -dir1 );
   3234 			c2.SetSize( 1 );
   3235 			c2[0] = 0.0f;
   3236 		}
   3237 
   3238 		lo[0] = -friction;
   3239 		hi[0] = friction;
   3240 		boxConstraint = cc;
   3241 		boxIndex[0] = 0;
   3242 	}
   3243 	else {
   3244 		// get two friction directions orthogonal to contact normal
   3245 		cc->GetContact().normal.NormalVectors( dir1, dir2 );
   3246 
   3247 		r = cc->GetContact().point - body1->GetWorldOrigin();
   3248 
   3249 		J1.SetSize( 2, 6 );
   3250 		J1.SubVec6(0).SubVec3(0) = dir1;
   3251 		J1.SubVec6(0).SubVec3(1) = r.Cross( dir1 );
   3252 		J1.SubVec6(1).SubVec3(0) = dir2;
   3253 		J1.SubVec6(1).SubVec3(1) = r.Cross( dir2 );
   3254 		c1.SetSize( 2 );
   3255 		c1[0] = c1[1] = 0.0f;
   3256 
   3257 		if ( body2 ) {
   3258 			r = cc->GetContact().point - body2->GetWorldOrigin();
   3259 
   3260 			J2.SetSize( 2, 6 );
   3261 			J2.SubVec6(0).SubVec3(0) = -dir1;
   3262 			J2.SubVec6(0).SubVec3(1) = r.Cross( -dir1 );
   3263 			J2.SubVec6(1).SubVec3(0) = -dir2;
   3264 			J2.SubVec6(1).SubVec3(1) = r.Cross( -dir2 );
   3265 			c2.SetSize( 2 );
   3266 			c2[0] = c2[1] = 0.0f;
   3267 
   3268 			if ( body2->GetContactFriction() < friction ) {
   3269 				friction = body2->GetContactFriction();
   3270 			}
   3271 		}
   3272 
   3273 		lo[0] = -friction;
   3274 		hi[0] = friction;
   3275 		boxConstraint = cc;
   3276 		boxIndex[0] = 0;
   3277 		lo[1] = -friction;
   3278 		hi[1] = friction;
   3279 		boxIndex[1] = 0;
   3280 	}
   3281 
   3282 	if ( body1->GetContactMotorDirection( dir1 ) && body1->GetContactMotorForce() > 0.0f ) {
   3283 		// project the motor force direction into the contact plane
   3284 		dir1 -= dir1 * cc->GetContact().normal * dir1;
   3285 		dir1.Normalize();
   3286 
   3287 		r = cc->GetContact().point - body1->GetWorldOrigin();
   3288 
   3289 		newRow = J1.GetNumRows();
   3290 		J1.ChangeSize( newRow+1, J1.GetNumColumns() );
   3291 		J1.SubVec6(newRow).SubVec3(0) = -dir1;
   3292 		J1.SubVec6(newRow).SubVec3(1) = r.Cross( -dir1 );
   3293 		c1.ChangeSize( newRow+1 );
   3294 		c1[newRow] = body1->GetContactMotorVelocity();
   3295 
   3296 		if ( body2 ) {
   3297 			r = cc->GetContact().point - body2->GetWorldOrigin();
   3298 
   3299 			J2.ChangeSize( newRow+1, J2.GetNumColumns() );
   3300 			J2.SubVec6(newRow).SubVec3(0) = -dir1;
   3301 			J2.SubVec6(newRow).SubVec3(1) = r.Cross( -dir1 );
   3302 			c2.ChangeSize( newRow+1 );
   3303 			c2[newRow] = 0.0f;
   3304 		}
   3305 
   3306 		lo[newRow] = -body1->GetContactMotorForce();
   3307 		hi[newRow] = body1->GetContactMotorForce();
   3308 		boxIndex[newRow] = -1;
   3309 	}
   3310 
   3311 	physics->AddFrameConstraint( this );
   3312 
   3313 	return true;
   3314 }
   3315 
   3316 /*
   3317 ================
   3318 idAFConstraint_ContactFriction::Translate
   3319 ================
   3320 */
   3321 void idAFConstraint_ContactFriction::Translate( const idVec3 &translation ) {
   3322 }
   3323 
   3324 /*
   3325 ================
   3326 idAFConstraint_ContactFriction::Rotate
   3327 ================
   3328 */
   3329 void idAFConstraint_ContactFriction::Rotate( const idRotation &rotation ) {
   3330 }
   3331 
   3332 /*
   3333 ================
   3334 idAFConstraint_ContactFriction::DebugDraw
   3335 ================
   3336 */
   3337 void idAFConstraint_ContactFriction::DebugDraw() {
   3338 }
   3339 
   3340 
   3341 //===============================================================
   3342 //
   3343 //	idAFConstraint_ConeLimit
   3344 //
   3345 //===============================================================
   3346 
   3347 /*
   3348 ================
   3349 idAFConstraint_ConeLimit::idAFConstraint_ConeLimit
   3350 ================
   3351 */
   3352 idAFConstraint_ConeLimit::idAFConstraint_ConeLimit() {
   3353 	type = CONSTRAINT_CONELIMIT;
   3354 	name = "coneLimit";
   3355 	InitSize( 1 );
   3356 	fl.allowPrimary = false;
   3357 	fl.frameConstraint = true;
   3358 }
   3359 
   3360 /*
   3361 ================
   3362 idAFConstraint_ConeLimit::Setup
   3363 
   3364   the coneAnchor is the top of the cone in body2 space
   3365   the coneAxis is the axis of the cone in body2 space
   3366   the coneAngle is the angle the cone hull makes at the top
   3367   the body1Axis is the axis in body1 space that should stay within the cone
   3368 ================
   3369 */
   3370 void idAFConstraint_ConeLimit::Setup( idAFBody *b1, idAFBody *b2, const idVec3 &coneAnchor, const idVec3 &coneAxis, const float coneAngle, const idVec3 &body1Axis ) {
   3371 	this->body1 = b1;
   3372 	this->body2 = b2;
   3373 	this->coneAxis = coneAxis;
   3374 	this->coneAxis.Normalize();
   3375 	this->coneAnchor = coneAnchor;
   3376 	this->body1Axis = body1Axis;
   3377 	this->body1Axis.Normalize();
   3378 	this->cosAngle = (float) cos( DEG2RAD( coneAngle * 0.5f ) );
   3379 	this->sinHalfAngle = (float) sin( DEG2RAD( coneAngle * 0.25f ) );
   3380 	this->cosHalfAngle = (float) cos( DEG2RAD( coneAngle * 0.25f ) );
   3381 }
   3382 
   3383 /*
   3384 ================
   3385 idAFConstraint_ConeLimit::SetAnchor
   3386 ================
   3387 */
   3388 void idAFConstraint_ConeLimit::SetAnchor( const idVec3 &coneAnchor ) {
   3389 	this->coneAnchor = coneAnchor;
   3390 }
   3391 
   3392 /*
   3393 ================
   3394 idAFConstraint_ConeLimit::SetBody1Axis
   3395 ================
   3396 */
   3397 void idAFConstraint_ConeLimit::SetBody1Axis( const idVec3 &body1Axis ) {
   3398 	this->body1Axis = body1Axis;
   3399 }
   3400 
   3401 /*
   3402 ================
   3403 idAFConstraint_ConeLimit::Evaluate
   3404 ================
   3405 */
   3406 void idAFConstraint_ConeLimit::Evaluate( float invTimeStep ) {
   3407 	// do nothing
   3408 }
   3409 
   3410 /*
   3411 ================
   3412 idAFConstraint_ConeLimit::ApplyFriction
   3413 ================
   3414 */
   3415 void idAFConstraint_ConeLimit::ApplyFriction( float invTimeStep ) {
   3416 }
   3417 
   3418 /*
   3419 ================
   3420 idAFConstraint_ConeLimit::Add
   3421 ================
   3422 */
   3423 bool idAFConstraint_ConeLimit::Add( idPhysics_AF *phys, float invTimeStep ) {
   3424 	float a;
   3425 	idVec6 J1row, J2row;
   3426 	idVec3 ax, anchor, body1ax, normal, coneVector, p1, p2;
   3427 	idQuat q;
   3428 	idAFBody *master;
   3429 
   3430 	if ( af_skipLimits.GetBool() ) {
   3431 		lm.Zero();	// constraint exerts no force
   3432 		return false;
   3433 	}
   3434 
   3435 	physics = phys;
   3436 
   3437 	master = body2 ? body2 : physics->GetMasterBody();
   3438 
   3439 	if ( master ) {
   3440 		ax = coneAxis * master->GetWorldAxis();
   3441 		anchor = master->GetWorldOrigin() + coneAnchor * master->GetWorldAxis();
   3442 	}
   3443 	else {
   3444 		ax = coneAxis;
   3445 		anchor = coneAnchor;
   3446 	}
   3447 
   3448 	body1ax = body1Axis * body1->GetWorldAxis();
   3449 
   3450 	a = ax * body1ax;
   3451 
   3452 	// if the body1 axis is inside the cone
   3453 	if ( a > cosAngle ) {
   3454 		lm.Zero();	// constraint exerts no force
   3455 		return false;
   3456 	}
   3457 
   3458 	// calculate the inward cone normal for the position the body1 axis went outside the cone
   3459 	normal = body1ax.Cross( ax );
   3460 	normal.Normalize();
   3461 	q.x = normal.x * sinHalfAngle;
   3462 	q.y = normal.y * sinHalfAngle;
   3463 	q.z = normal.z * sinHalfAngle;
   3464 	q.w = cosHalfAngle;
   3465 	coneVector = ax * q.ToMat3();
   3466 	normal = coneVector.Cross( ax ).Cross( coneVector );
   3467 	normal.Normalize();
   3468 
   3469 	p1 = anchor + 32.0f * coneVector - body1->GetWorldOrigin();
   3470 
   3471 	J1row.SubVec3(0) = normal;
   3472 	J1row.SubVec3(1) = p1.Cross( normal );
   3473 	J1.Set( 1, 6, J1row.ToFloatPtr() );
   3474 
   3475 	c1[0] = (invTimeStep * LIMIT_ERROR_REDUCTION) * ( normal * (32.0f * body1ax) );
   3476 
   3477 	if ( body2 ) {
   3478 
   3479 		p2 = anchor + 32.0f * coneVector - master->GetWorldOrigin();
   3480 
   3481 		J2row.SubVec3(0) = -normal;
   3482 		J2row.SubVec3(1) = p2.Cross( -normal );
   3483 		J2.Set( 1, 6, J2row.ToFloatPtr() );
   3484 
   3485 		c2[0] = 0.0f;
   3486 	}
   3487 
   3488 	lo[0] = 0.0f;
   3489 	e[0] = LIMIT_LCP_EPSILON;
   3490 
   3491 	physics->AddFrameConstraint( this );
   3492 
   3493 	return true;
   3494 }
   3495 
   3496 /*
   3497 ================
   3498 idAFConstraint_ConeLimit::Translate
   3499 ================
   3500 */
   3501 void idAFConstraint_ConeLimit::Translate( const idVec3 &translation ) {
   3502 	if ( !body2 ) {
   3503 		coneAnchor += translation;
   3504 	}
   3505 }
   3506 
   3507 /*
   3508 ================
   3509 idAFConstraint_ConeLimit::Rotate
   3510 ================
   3511 */
   3512 void idAFConstraint_ConeLimit::Rotate( const idRotation &rotation ) {
   3513 	if ( !body2 ) {
   3514 		coneAnchor *= rotation;
   3515 		coneAxis *= rotation.ToMat3();
   3516 	}
   3517 }
   3518 
   3519 /*
   3520 ================
   3521 idAFConstraint_ConeLimit::DebugDraw
   3522 ================
   3523 */
   3524 void idAFConstraint_ConeLimit::DebugDraw() {
   3525 	idVec3 ax, anchor, x, y, z, start, end;
   3526 	float sinAngle, a, size = 10.0f;
   3527 	idAFBody *master;
   3528 
   3529 	master = body2 ? body2 : physics->GetMasterBody();
   3530 
   3531 	if ( master ) {
   3532 		ax = coneAxis * master->GetWorldAxis();
   3533 		anchor = master->GetWorldOrigin() + coneAnchor * master->GetWorldAxis();
   3534 	}
   3535 	else {
   3536 		ax = coneAxis;
   3537 		anchor = coneAnchor;
   3538 	}
   3539 
   3540 	// draw body1 axis
   3541 	gameRenderWorld->DebugLine( colorGreen, anchor, anchor + size * (body1Axis * body1->GetWorldAxis()) );
   3542 
   3543 	// draw cone
   3544 	ax.NormalVectors( x, y );
   3545 	sinAngle = idMath::Sqrt( 1.0f - cosAngle * cosAngle );
   3546 	x *= size * sinAngle;
   3547 	y *= size * sinAngle;
   3548 	z = anchor + ax * size * cosAngle;
   3549 	start = x + z;
   3550 	for ( a = 0.0f; a < 360.0f; a += 45.0f ) {
   3551 		end = x * (float) cos( DEG2RAD(a + 45.0f) ) + y * (float) sin( DEG2RAD(a + 45.0f) ) + z;
   3552 		gameRenderWorld->DebugLine( colorMagenta, anchor, start );
   3553 		gameRenderWorld->DebugLine( colorMagenta, start, end );
   3554 		start = end;
   3555 	}
   3556 }
   3557 
   3558 /*
   3559 ================
   3560 idAFConstraint_ConeLimit::Save
   3561 ================
   3562 */
   3563 void idAFConstraint_ConeLimit::Save( idSaveGame *saveFile ) const {
   3564 	idAFConstraint::Save( saveFile );
   3565 	saveFile->WriteVec3( coneAnchor );
   3566 	saveFile->WriteVec3( coneAxis );
   3567 	saveFile->WriteVec3( body1Axis );
   3568 	saveFile->WriteFloat( cosAngle );
   3569 	saveFile->WriteFloat( sinHalfAngle );
   3570 	saveFile->WriteFloat( cosHalfAngle );
   3571 	saveFile->WriteFloat( epsilon );
   3572 }
   3573 
   3574 /*
   3575 ================
   3576 idAFConstraint_ConeLimit::Restore
   3577 ================
   3578 */
   3579 void idAFConstraint_ConeLimit::Restore( idRestoreGame *saveFile ) {
   3580 	idAFConstraint::Restore( saveFile );
   3581 	saveFile->ReadVec3( coneAnchor );
   3582 	saveFile->ReadVec3( coneAxis );
   3583 	saveFile->ReadVec3( body1Axis );
   3584 	saveFile->ReadFloat( cosAngle );
   3585 	saveFile->ReadFloat( sinHalfAngle );
   3586 	saveFile->ReadFloat( cosHalfAngle );
   3587 	saveFile->ReadFloat( epsilon );
   3588 }
   3589 
   3590 
   3591 //===============================================================
   3592 //
   3593 //	idAFConstraint_PyramidLimit
   3594 //
   3595 //===============================================================
   3596 
   3597 /*
   3598 ================
   3599 idAFConstraint_PyramidLimit::idAFConstraint_PyramidLimit
   3600 ================
   3601 */
   3602 idAFConstraint_PyramidLimit::idAFConstraint_PyramidLimit() {
   3603 	type = CONSTRAINT_PYRAMIDLIMIT;
   3604 	name = "pyramidLimit";
   3605 	InitSize( 1 );
   3606 	fl.allowPrimary = false;
   3607 	fl.frameConstraint = true;
   3608 }
   3609 
   3610 /*
   3611 ================
   3612 idAFConstraint_PyramidLimit::Setup
   3613 ================
   3614 */
   3615 void idAFConstraint_PyramidLimit::Setup( idAFBody *b1, idAFBody *b2, const idVec3 &pyramidAnchor,
   3616 								const idVec3 &pyramidAxis, const idVec3 &baseAxis,
   3617 								const float pyramidAngle1, const float pyramidAngle2, const idVec3 &body1Axis ) {
   3618 	body1 = b1;
   3619 	body2 = b2;
   3620 	// setup the base and make sure the basis is orthonormal
   3621 	pyramidBasis[2] = pyramidAxis;
   3622 	pyramidBasis[2].Normalize();
   3623 	pyramidBasis[0] = baseAxis;
   3624 	pyramidBasis[0] -= pyramidBasis[2] * baseAxis * pyramidBasis[2];
   3625 	pyramidBasis[0].Normalize();
   3626 	pyramidBasis[1] = pyramidBasis[0].Cross( pyramidBasis[2] );
   3627 	// pyramid top
   3628 	this->pyramidAnchor = pyramidAnchor;
   3629 	// angles
   3630 	cosAngle[0] = (float) cos( DEG2RAD( pyramidAngle1 * 0.5f ) );
   3631 	cosAngle[1] = (float) cos( DEG2RAD( pyramidAngle2 * 0.5f ) );
   3632 	sinHalfAngle[0] = (float) sin( DEG2RAD( pyramidAngle1 * 0.25f ) );
   3633 	sinHalfAngle[1] = (float) sin( DEG2RAD( pyramidAngle2 * 0.25f ) );
   3634 	cosHalfAngle[0] = (float) cos( DEG2RAD( pyramidAngle1 * 0.25f ) );
   3635 	cosHalfAngle[1] = (float) cos( DEG2RAD( pyramidAngle2 * 0.25f ) );
   3636 
   3637 	this->body1Axis = body1Axis;
   3638 }
   3639 
   3640 /*
   3641 ================
   3642 idAFConstraint_PyramidLimit::SetAnchor
   3643 ================
   3644 */
   3645 void idAFConstraint_PyramidLimit::SetAnchor( const idVec3 &pyramidAnchor ) {
   3646 	this->pyramidAnchor = pyramidAnchor;
   3647 }
   3648 
   3649 /*
   3650 ================
   3651 idAFConstraint_PyramidLimit::SetBody1Axis
   3652 ================
   3653 */
   3654 void idAFConstraint_PyramidLimit::SetBody1Axis( const idVec3 &body1Axis ) {
   3655 	this->body1Axis = body1Axis;
   3656 }
   3657 
   3658 /*
   3659 ================
   3660 idAFConstraint_PyramidLimit::Evaluate
   3661 ================
   3662 */
   3663 void idAFConstraint_PyramidLimit::Evaluate( float invTimeStep ) {
   3664 	// do nothing
   3665 }
   3666 
   3667 /*
   3668 ================
   3669 idAFConstraint_PyramidLimit::ApplyFriction
   3670 ================
   3671 */
   3672 void idAFConstraint_PyramidLimit::ApplyFriction( float invTimeStep ) {
   3673 }
   3674 
   3675 /*
   3676 ================
   3677 idAFConstraint_PyramidLimit::Add
   3678 ================
   3679 */
   3680 bool idAFConstraint_PyramidLimit::Add( idPhysics_AF *phys, float invTimeStep ) {
   3681 	int i;
   3682 	float a[2];
   3683 	idVec6 J1row, J2row;
   3684 	idMat3 worldBase;
   3685 	idVec3 anchor, body1ax, ax[2], v, normal, pyramidVector, p1, p2;
   3686 	idQuat q;
   3687 	idAFBody *master;
   3688 
   3689 	if ( af_skipLimits.GetBool() ) {
   3690 		lm.Zero();	// constraint exerts no force
   3691 		return false;
   3692 	}
   3693 
   3694 	physics = phys;
   3695 	master = body2 ? body2 : physics->GetMasterBody();
   3696 
   3697 	if ( master ) {
   3698 		worldBase[0] = pyramidBasis[0] * master->GetWorldAxis();
   3699 		worldBase[1] = pyramidBasis[1] * master->GetWorldAxis();
   3700 		worldBase[2] = pyramidBasis[2] * master->GetWorldAxis();
   3701 		anchor = master->GetWorldOrigin() + pyramidAnchor * master->GetWorldAxis();
   3702 	}
   3703 	else {
   3704 		worldBase = pyramidBasis;
   3705 		anchor = pyramidAnchor;
   3706 	}
   3707 
   3708 	body1ax = body1Axis * body1->GetWorldAxis();
   3709 
   3710 	for ( i = 0; i < 2; i++ ) {
   3711 		ax[i] = body1ax - worldBase[!i] * body1ax * worldBase[!i];
   3712 		ax[i].Normalize();
   3713 		a[i] = worldBase[2] * ax[i];
   3714 	}
   3715 
   3716 	// if the body1 axis is inside the pyramid
   3717 	if ( a[0] > cosAngle[0] && a[1] > cosAngle[1] ) {
   3718 		lm.Zero();	// constraint exerts no force
   3719 		return false;
   3720 	}
   3721 
   3722 	// calculate the inward pyramid normal for the position the body1 axis went outside the pyramid
   3723 	pyramidVector = worldBase[2];
   3724 	for ( i = 0; i < 2; i++ ) {
   3725 		if ( a[i] <= cosAngle[i] ) {
   3726 			v = ax[i].Cross( worldBase[2] );
   3727 			v.Normalize();
   3728 			q.x = v.x * sinHalfAngle[i];
   3729 			q.y = v.y * sinHalfAngle[i];
   3730 			q.z = v.z * sinHalfAngle[i];
   3731 			q.w = cosHalfAngle[i];
   3732 			pyramidVector *= q.ToMat3();
   3733 		}
   3734 	}
   3735 	normal = pyramidVector.Cross( worldBase[2] ).Cross( pyramidVector );
   3736 	normal.Normalize();
   3737 
   3738 	p1 = anchor + 32.0f * pyramidVector - body1->GetWorldOrigin();
   3739 
   3740 	J1row.SubVec3(0) = normal;
   3741 	J1row.SubVec3(1) = p1.Cross( normal );
   3742 	J1.Set( 1, 6, J1row.ToFloatPtr() );
   3743 
   3744 	c1[0] = (invTimeStep * LIMIT_ERROR_REDUCTION) * ( normal * (32.0f * body1ax) );
   3745 
   3746 	if ( body2 ) {
   3747 
   3748 		p2 = anchor + 32.0f * pyramidVector - master->GetWorldOrigin();
   3749 
   3750 		J2row.SubVec3(0) = -normal;
   3751 		J2row.SubVec3(1) = p2.Cross( -normal );
   3752 		J2.Set( 1, 6, J2row.ToFloatPtr() );
   3753 
   3754 		c2[0] = 0.0f;
   3755 	}
   3756 
   3757 	lo[0] = 0.0f;
   3758 	e[0] = LIMIT_LCP_EPSILON;
   3759 
   3760 	physics->AddFrameConstraint( this );
   3761 
   3762 	return true;
   3763 }
   3764 
   3765 /*
   3766 ================
   3767 idAFConstraint_PyramidLimit::Translate
   3768 ================
   3769 */
   3770 void idAFConstraint_PyramidLimit::Translate( const idVec3 &translation ) {
   3771 	if ( !body2 ) {
   3772 		pyramidAnchor += translation;
   3773 	}
   3774 }
   3775 
   3776 /*
   3777 ================
   3778 idAFConstraint_PyramidLimit::Rotate
   3779 ================
   3780 */
   3781 void idAFConstraint_PyramidLimit::Rotate( const idRotation &rotation ) {
   3782 	if ( !body2 ) {
   3783 		pyramidAnchor *= rotation;
   3784 		pyramidBasis[0] *= rotation.ToMat3();
   3785 		pyramidBasis[1] *= rotation.ToMat3();
   3786 		pyramidBasis[2] *= rotation.ToMat3();
   3787 	}
   3788 }
   3789 
   3790 /*
   3791 ================
   3792 idAFConstraint_PyramidLimit::DebugDraw
   3793 ================
   3794 */
   3795 void idAFConstraint_PyramidLimit::DebugDraw() {
   3796 	int i;
   3797 	float size = 10.0f;
   3798 	idVec3 anchor, dir, p[4];
   3799 	idMat3 worldBase, m[2];
   3800 	idQuat q;
   3801 	idAFBody *master;
   3802 
   3803 	master = body2 ? body2 : physics->GetMasterBody();
   3804 
   3805 	if ( master ) {
   3806 		worldBase[0] = pyramidBasis[0] * master->GetWorldAxis();
   3807 		worldBase[1] = pyramidBasis[1] * master->GetWorldAxis();
   3808 		worldBase[2] = pyramidBasis[2] * master->GetWorldAxis();
   3809 		anchor = master->GetWorldOrigin() + pyramidAnchor * master->GetWorldAxis();
   3810 	}
   3811 	else {
   3812 		worldBase = pyramidBasis;
   3813 		anchor = pyramidAnchor;
   3814 	}
   3815 
   3816 	// draw body1 axis
   3817 	gameRenderWorld->DebugLine( colorGreen, anchor, anchor + size * (body1Axis * body1->GetWorldAxis()) );
   3818 
   3819 	// draw the pyramid
   3820 	for ( i = 0; i < 2; i++ ) {
   3821 		q.x = worldBase[!i].x * sinHalfAngle[i];
   3822 		q.y = worldBase[!i].y * sinHalfAngle[i];
   3823 		q.z = worldBase[!i].z * sinHalfAngle[i];
   3824 		q.w = cosHalfAngle[i];
   3825 		m[i] = q.ToMat3();
   3826 	}
   3827 
   3828 	dir = worldBase[2] * size;
   3829 	p[0] = anchor + m[0] * (m[1] * dir);
   3830 	p[1] = anchor + m[0] * (m[1].Transpose() * dir);
   3831 	p[2] = anchor + m[0].Transpose() * (m[1].Transpose() * dir);
   3832 	p[3] = anchor + m[0].Transpose() * (m[1] * dir);
   3833 
   3834 	for ( i = 0; i < 4; i++ ) {
   3835 		gameRenderWorld->DebugLine( colorMagenta, anchor, p[i] );
   3836 		gameRenderWorld->DebugLine( colorMagenta, p[i], p[(i+1)&3] );
   3837 	}
   3838 }
   3839 
   3840 /*
   3841 ================
   3842 idAFConstraint_PyramidLimit::Save
   3843 ================
   3844 */
   3845 void idAFConstraint_PyramidLimit::Save( idSaveGame *saveFile ) const {
   3846 	idAFConstraint::Save( saveFile );
   3847 	saveFile->WriteVec3( pyramidAnchor );
   3848 	saveFile->WriteMat3( pyramidBasis );
   3849 	saveFile->WriteVec3( body1Axis );
   3850 	saveFile->WriteFloat( cosAngle[0] );
   3851 	saveFile->WriteFloat( cosAngle[1] );
   3852 	saveFile->WriteFloat( sinHalfAngle[0] );
   3853 	saveFile->WriteFloat( sinHalfAngle[1] );
   3854 	saveFile->WriteFloat( cosHalfAngle[0] );
   3855 	saveFile->WriteFloat( cosHalfAngle[1] );
   3856 	saveFile->WriteFloat( epsilon );
   3857 }
   3858 
   3859 /*
   3860 ================
   3861 idAFConstraint_PyramidLimit::Restore
   3862 ================
   3863 */
   3864 void idAFConstraint_PyramidLimit::Restore( idRestoreGame *saveFile ) {
   3865 	idAFConstraint::Restore( saveFile );
   3866 	saveFile->ReadVec3( pyramidAnchor );
   3867 	saveFile->ReadMat3( pyramidBasis );
   3868 	saveFile->ReadVec3( body1Axis );
   3869 	saveFile->ReadFloat( cosAngle[0] );
   3870 	saveFile->ReadFloat( cosAngle[1] );
   3871 	saveFile->ReadFloat( sinHalfAngle[0] );
   3872 	saveFile->ReadFloat( sinHalfAngle[1] );
   3873 	saveFile->ReadFloat( cosHalfAngle[0] );
   3874 	saveFile->ReadFloat( cosHalfAngle[1] );
   3875 	saveFile->ReadFloat( epsilon );
   3876 }
   3877 
   3878 
   3879 //===============================================================
   3880 //
   3881 //	idAFConstraint_Suspension
   3882 //
   3883 //===============================================================
   3884 
   3885 /*
   3886 ================
   3887 idAFConstraint_Suspension::idAFConstraint_Suspension
   3888 ================
   3889 */
   3890 idAFConstraint_Suspension::idAFConstraint_Suspension() {
   3891 	type = CONSTRAINT_SUSPENSION;
   3892 	name = "suspension";
   3893 	InitSize( 3 );
   3894 	fl.allowPrimary = false;
   3895 	fl.frameConstraint = true;
   3896 
   3897 	localOrigin.Zero();
   3898 	localAxis.Identity();
   3899 	suspensionUp = 0.0f;
   3900 	suspensionDown = 0.0f;
   3901 	suspensionKCompress = 0.0f;
   3902 	suspensionDamping = 0.0f;
   3903 	steerAngle = 0.0f;
   3904 	friction = 2.0f;
   3905 	motorEnabled = false;
   3906 	motorForce = 0.0f;
   3907 	motorVelocity = 0.0f;
   3908 	wheelModel = NULL;
   3909 	memset( &trace, 0, sizeof( trace ) );
   3910 	epsilon = LCP_EPSILON;
   3911 }
   3912 
   3913 /*
   3914 ================
   3915 idAFConstraint_Suspension::Setup
   3916 ================
   3917 */
   3918 void idAFConstraint_Suspension::Setup( const char *name, idAFBody *body, const idVec3 &origin, const idMat3 &axis, idClipModel *clipModel ) {
   3919 	this->name = name;
   3920 	body1 = body;
   3921 	body2 = NULL;
   3922 	localOrigin = ( origin - body->GetWorldOrigin() ) * body->GetWorldAxis().Transpose();
   3923 	localAxis = axis * body->GetWorldAxis().Transpose();
   3924 	wheelModel = clipModel;
   3925 }
   3926 
   3927 /*
   3928 ================
   3929 idAFConstraint_Suspension::SetSuspension
   3930 ================
   3931 */
   3932 void idAFConstraint_Suspension::SetSuspension( const float up, const float down, const float k, const float d, const float f ) {
   3933 	suspensionUp = up;
   3934 	suspensionDown = down;
   3935 	suspensionKCompress = k;
   3936 	suspensionDamping = d;
   3937 	friction = f;
   3938 }
   3939 
   3940 /*
   3941 ================
   3942 idAFConstraint_Suspension::GetWheelOrigin
   3943 ================
   3944 */
   3945 const idVec3 idAFConstraint_Suspension::GetWheelOrigin() const {
   3946 	return body1->GetWorldOrigin() + wheelOffset * body1->GetWorldAxis();
   3947 }
   3948 
   3949 /*
   3950 ================
   3951 idAFConstraint_Suspension::Evaluate
   3952 ================
   3953 */
   3954 void idAFConstraint_Suspension::Evaluate( float invTimeStep ) {
   3955 	float velocity, suspensionLength, springLength, compression, dampingForce, springForce;
   3956 	idVec3 origin, start, end, vel1, vel2, springDir, r, frictionDir, motorDir;
   3957 	idMat3 axis;
   3958 	idRotation rotation;
   3959 
   3960 	axis = localAxis * body1->GetWorldAxis();
   3961 	origin = body1->GetWorldOrigin() + localOrigin * body1->GetWorldAxis();
   3962 	start = origin + suspensionUp * axis[2];
   3963 	end = origin - suspensionDown * axis[2];
   3964 
   3965 	rotation.SetVec( axis[2] );
   3966 	rotation.SetAngle( steerAngle );
   3967 
   3968 	axis *= rotation.ToMat3();
   3969 
   3970 	gameLocal.clip.Translation( trace, start, end, wheelModel, axis, MASK_SOLID, NULL );
   3971 
   3972 	wheelOffset = ( trace.endpos - body1->GetWorldOrigin() ) * body1->GetWorldAxis().Transpose();
   3973 
   3974 	if ( trace.fraction >= 1.0f ) {
   3975 		J1.SetSize( 0, 6 );
   3976 		if ( body2 ) {
   3977 			J2.SetSize( 0, 6 );
   3978 		}
   3979 		return;
   3980 	}
   3981 
   3982 	// calculate and add spring force
   3983 	vel1 = body1->GetPointVelocity( start );
   3984 	if ( body2 ) {
   3985 		vel2 = body2->GetPointVelocity( trace.c.point );
   3986 	} else {
   3987 		vel2.Zero();
   3988 	}
   3989 
   3990 	suspensionLength = suspensionUp + suspensionDown;
   3991 	springDir = trace.endpos - start;
   3992 	springLength = trace.fraction * suspensionLength;
   3993 	dampingForce = suspensionDamping * idMath::Fabs( ( vel2 - vel1 ) * springDir ) / ( 1.0f + springLength * springLength );
   3994 	compression = suspensionLength - springLength;
   3995 	springForce = compression * compression * suspensionKCompress - dampingForce;
   3996 
   3997 	r = trace.c.point - body1->GetWorldOrigin();
   3998 	J1.SetSize( 2, 6 );
   3999 	J1.SubVec6(0).SubVec3(0) = trace.c.normal;
   4000 	J1.SubVec6(0).SubVec3(1) = r.Cross( trace.c.normal );
   4001 	c1.SetSize( 2 );
   4002 	c1[0] = 0.0f;
   4003 	velocity = J1.SubVec6(0).SubVec3(0) * body1->GetLinearVelocity() + J1.SubVec6(0).SubVec3(1) * body1->GetAngularVelocity();
   4004 
   4005 	if ( body2 ) {
   4006 		r = trace.c.point - body2->GetWorldOrigin();
   4007 		J2.SetSize( 2, 6 );
   4008 		J2.SubVec6(0).SubVec3(0) = -trace.c.normal;
   4009 		J2.SubVec6(0).SubVec3(1) = r.Cross( -trace.c.normal );
   4010 		c2.SetSize( 2 );
   4011 		c2[0] = 0.0f;
   4012 		velocity += J2.SubVec6(0).SubVec3(0) * body2->GetLinearVelocity() + J2.SubVec6(0).SubVec3(1) * body2->GetAngularVelocity();
   4013 	}
   4014 
   4015 	c1[0] = -compression;		// + 0.5f * -velocity;
   4016 
   4017 	e[0] = 1e-4f;
   4018 	lo[0] = 0.0f;
   4019 	hi[0] = springForce;
   4020 	boxConstraint = NULL;
   4021 	boxIndex[0] = -1;
   4022 
   4023 	// project the friction direction into the contact plane
   4024 	frictionDir = axis[1] - axis[1] * trace.c.normal * axis[1];
   4025 	frictionDir.Normalize();
   4026 
   4027 	r = trace.c.point - body1->GetWorldOrigin();
   4028 
   4029 	J1.SubVec6(1).SubVec3(0) = frictionDir;
   4030 	J1.SubVec6(1).SubVec3(1) = r.Cross( frictionDir );
   4031 	c1[1] = 0.0f;
   4032 
   4033 	if ( body2 ) {
   4034 		r = trace.c.point - body2->GetWorldOrigin();
   4035 
   4036 		J2.SubVec6(1).SubVec3(0) = -frictionDir;
   4037 		J2.SubVec6(1).SubVec3(1) = r.Cross( -frictionDir );
   4038 		c2[1] = 0.0f;
   4039 	}
   4040 
   4041 	lo[1] = -friction * physics->GetContactFrictionScale();
   4042 	hi[1] = friction * physics->GetContactFrictionScale();
   4043 
   4044 	boxConstraint = this;
   4045 	boxIndex[1] = 0;
   4046 
   4047 
   4048 	if ( motorEnabled ) {
   4049 		// project the motor force direction into the contact plane
   4050 		motorDir = axis[0] - axis[0] * trace.c.normal * axis[0];
   4051 		motorDir.Normalize();
   4052 
   4053 		r = trace.c.point - body1->GetWorldOrigin();
   4054 
   4055 		J1.ChangeSize( 3, J1.GetNumColumns() );
   4056 		J1.SubVec6(2).SubVec3(0) = -motorDir;
   4057 		J1.SubVec6(2).SubVec3(1) = r.Cross( -motorDir );
   4058 		c1.ChangeSize( 3 );
   4059 		c1[2] = motorVelocity;
   4060 
   4061 		if ( body2 ) {
   4062 			r = trace.c.point - body2->GetWorldOrigin();
   4063 
   4064 			J2.ChangeSize( 3, J2.GetNumColumns() );
   4065 			J2.SubVec6(2).SubVec3(0) = -motorDir;
   4066 			J2.SubVec6(2).SubVec3(1) = r.Cross( -motorDir );
   4067 			c2.ChangeSize( 3 );
   4068 			c2[2] = 0.0f;
   4069 		}
   4070 
   4071 		lo[2] = -motorForce;
   4072 		hi[2] = motorForce;
   4073 		boxIndex[2] = -1;
   4074 	}
   4075 }
   4076 
   4077 /*
   4078 ================
   4079 idAFConstraint_Suspension::ApplyFriction
   4080 ================
   4081 */
   4082 void idAFConstraint_Suspension::ApplyFriction( float invTimeStep ) {
   4083 	// do nothing
   4084 }
   4085 
   4086 /*
   4087 ================
   4088 idAFConstraint_Suspension::Translate
   4089 ================
   4090 */
   4091 void idAFConstraint_Suspension::Translate( const idVec3 &translation ) {
   4092 }
   4093 
   4094 /*
   4095 ================
   4096 idAFConstraint_Suspension::Rotate
   4097 ================
   4098 */
   4099 void idAFConstraint_Suspension::Rotate( const idRotation &rotation ) {
   4100 }
   4101 
   4102 /*
   4103 ================
   4104 idAFConstraint_Suspension::DebugDraw
   4105 ================
   4106 */
   4107 void idAFConstraint_Suspension::DebugDraw() {
   4108 	idVec3 origin;
   4109 	idMat3 axis;
   4110 	idRotation rotation;
   4111 
   4112 	axis = localAxis * body1->GetWorldAxis();
   4113 
   4114 	rotation.SetVec( axis[2] );
   4115 	rotation.SetAngle( steerAngle );
   4116 
   4117 	axis *= rotation.ToMat3();
   4118 
   4119 	if ( trace.fraction < 1.0f ) {
   4120 		origin = trace.c.point;
   4121 
   4122 		gameRenderWorld->DebugLine( colorWhite, origin, origin + 6.0f * axis[2] );
   4123 		gameRenderWorld->DebugLine( colorWhite, origin - 4.0f * axis[0], origin + 4.0f * axis[0] );
   4124 		gameRenderWorld->DebugLine( colorWhite, origin - 2.0f * axis[1], origin + 2.0f * axis[1] );
   4125 	}
   4126 }
   4127 
   4128 
   4129 //===============================================================
   4130 //
   4131 //	idAFBody
   4132 //
   4133 //===============================================================
   4134 
   4135 /*
   4136 ================
   4137 idAFBody::idAFBody
   4138 ================
   4139 */
   4140 idAFBody::idAFBody() {
   4141 	Init();
   4142 }
   4143 
   4144 /*
   4145 ================
   4146 idAFBody::idAFBody
   4147 ================
   4148 */
   4149 idAFBody::idAFBody( const idStr &name, idClipModel *clipModel, float density ) {
   4150 
   4151 	assert( clipModel );
   4152 	assert( clipModel->IsTraceModel() );
   4153 
   4154 	Init();
   4155 
   4156 	this->name = name;
   4157 	this->clipModel = NULL;
   4158 
   4159 	SetClipModel( clipModel );
   4160 	SetDensity( density );
   4161 
   4162 	current->worldOrigin = clipModel->GetOrigin();
   4163 	current->worldAxis = clipModel->GetAxis();
   4164 	*next = *current;
   4165 
   4166 }
   4167 
   4168 /*
   4169 ================
   4170 idAFBody::~idAFBody
   4171 ================
   4172 */
   4173 idAFBody::~idAFBody() {
   4174 	delete clipModel;
   4175 }
   4176 
   4177 /*
   4178 ================
   4179 idAFBody::Init
   4180 ================
   4181 */
   4182 void idAFBody::Init() {
   4183 	name						= "noname";
   4184 	parent						= NULL;
   4185 	clipModel					= NULL;
   4186 	primaryConstraint			= NULL;
   4187 	tree						= NULL;
   4188 
   4189 	linearFriction				= -1.0f;
   4190 	angularFriction				= -1.0f;
   4191 	contactFriction				= -1.0f;
   4192 	bouncyness					= -1.0f;
   4193 	clipMask					= 0;
   4194 
   4195 	frictionDir					= vec3_zero;
   4196 	contactMotorDir				= vec3_zero;
   4197 	contactMotorVelocity		= 0.0f;
   4198 	contactMotorForce			= 0.0f;
   4199 
   4200 	mass						= 1.0f;
   4201 	invMass						= 1.0f;
   4202 	centerOfMass				= vec3_zero;
   4203 	inertiaTensor				= mat3_identity;
   4204 	inverseInertiaTensor		= mat3_identity;
   4205 
   4206 	current						= &state[0];
   4207 	next						= &state[1];
   4208 	current->worldOrigin		= vec3_zero;
   4209 	current->worldAxis			= mat3_identity;
   4210 	current->spatialVelocity	= vec6_zero;
   4211 	current->externalForce		= vec6_zero;
   4212 	*next						= *current;
   4213 	saved						= *current;
   4214 	atRestOrigin				= vec3_zero;
   4215 	atRestAxis					= mat3_identity;
   4216 
   4217 	s.Zero( 6 );
   4218 	totalForce.Zero( 6 );
   4219 	auxForce.Zero( 6 );
   4220 	acceleration.Zero( 6 );
   4221 
   4222 	response					= NULL;
   4223 	responseIndex				= NULL;
   4224 	numResponses				= 0;
   4225 	maxAuxiliaryIndex			= 0;
   4226 	maxSubTreeAuxiliaryIndex	= 0;
   4227 
   4228 	memset( &fl, 0, sizeof( fl ) );
   4229 
   4230 	fl.selfCollision			= true;
   4231 	fl.isZero					= true;
   4232 }
   4233 
   4234 /*
   4235 ================
   4236 idAFBody::SetClipModel
   4237 ================
   4238 */
   4239 void idAFBody::SetClipModel( idClipModel *clipModel ) {
   4240 	if ( this->clipModel && this->clipModel != clipModel ) {
   4241 		delete this->clipModel;
   4242 	}
   4243 	this->clipModel = clipModel;
   4244 }
   4245 
   4246 /*
   4247 ================
   4248 idAFBody::SetFriction
   4249 ================
   4250 */
   4251 void idAFBody::SetFriction( float linear, float angular, float contact ) {
   4252 	if ( linear < 0.0f || linear > 1.0f ||
   4253 			angular < 0.0f || angular > 1.0f ||
   4254 				contact < 0.0f ) {
   4255 		gameLocal.Warning( "idAFBody::SetFriction: friction out of range, linear = %.1f, angular = %.1f, contact = %.1f", linear, angular, contact );
   4256 		return;
   4257 	}
   4258 	linearFriction = linear;
   4259 	angularFriction = angular;
   4260 	contactFriction = contact;
   4261 }
   4262 
   4263 /*
   4264 ================
   4265 idAFBody::SetBouncyness
   4266 ================
   4267 */
   4268 void idAFBody::SetBouncyness( float bounce ) {
   4269 	if ( bounce < 0.0f || bounce > 1.0f ) {
   4270 		gameLocal.Warning( "idAFBody::SetBouncyness: bouncyness out of range, bounce = %.1f", bounce );
   4271 		return;
   4272 	}
   4273 	bouncyness = bounce;
   4274 }
   4275 
   4276 /*
   4277 ================
   4278 idAFBody::SetDensity
   4279 ================
   4280 */
   4281 void idAFBody::SetDensity( float density, const idMat3 &inertiaScale ) {
   4282 
   4283 	// get the body mass properties
   4284 	clipModel->GetMassProperties( density, mass, centerOfMass, inertiaTensor );
   4285 
   4286 	// make sure we have a valid mass
   4287 	if ( mass <= 0.0f || IEEE_FLT_IS_NAN( mass ) ) {
   4288 		gameLocal.Warning( "idAFBody::SetDensity: invalid mass for body '%s'", name.c_str() );
   4289 		mass = 1.0f;
   4290 		centerOfMass.Zero();
   4291 		inertiaTensor.Identity();
   4292 	}
   4293 
   4294 	// make sure the center of mass is at the body origin
   4295 	if ( !centerOfMass.Compare( vec3_origin, CENTER_OF_MASS_EPSILON ) ) {
   4296 		gameLocal.Warning( "idAFBody::SetDentity: center of mass not at origin for body '%s'", name.c_str() );
   4297 	}
   4298 	centerOfMass.Zero();
   4299 
   4300 	// calculate the inverse mass and inverse inertia tensor
   4301 	invMass = 1.0f / mass;
   4302 	if ( inertiaScale != mat3_identity ) {
   4303 		inertiaTensor *= inertiaScale;
   4304 	}
   4305 	if ( inertiaTensor.IsDiagonal( 1e-3f ) ) {
   4306 		inertiaTensor[0][1] = inertiaTensor[0][2] = 0.0f;
   4307 		inertiaTensor[1][0] = inertiaTensor[1][2] = 0.0f;
   4308 		inertiaTensor[2][0] = inertiaTensor[2][1] = 0.0f;
   4309 		inverseInertiaTensor.Identity();
   4310 		inverseInertiaTensor[0][0] = 1.0f / inertiaTensor[0][0];
   4311 		inverseInertiaTensor[1][1] = 1.0f / inertiaTensor[1][1];
   4312 		inverseInertiaTensor[2][2] = 1.0f / inertiaTensor[2][2];
   4313 	}
   4314 	else {
   4315 		inverseInertiaTensor = inertiaTensor.Inverse();
   4316 	}
   4317 }
   4318 
   4319 /*
   4320 ================
   4321 idAFBody::SetFrictionDirection
   4322 ================
   4323 */
   4324 void idAFBody::SetFrictionDirection( const idVec3 &dir ) {
   4325 	frictionDir = dir * current->worldAxis.Transpose();
   4326 	fl.useFrictionDir = true;
   4327 }
   4328 
   4329 /*
   4330 ================
   4331 idAFBody::GetFrictionDirection
   4332 ================
   4333 */
   4334 bool idAFBody::GetFrictionDirection( idVec3 &dir ) const {
   4335 	if ( fl.useFrictionDir ) {
   4336 		dir = frictionDir * current->worldAxis;
   4337 		return true;
   4338 	}
   4339 	return false;
   4340 }
   4341 
   4342 /*
   4343 ================
   4344 idAFBody::SetContactMotorDirection
   4345 ================
   4346 */
   4347 void idAFBody::SetContactMotorDirection( const idVec3 &dir ) {
   4348 	contactMotorDir = dir * current->worldAxis.Transpose();
   4349 	fl.useContactMotorDir = true;
   4350 }
   4351 
   4352 /*
   4353 ================
   4354 idAFBody::GetContactMotorDirection
   4355 ================
   4356 */
   4357 bool idAFBody::GetContactMotorDirection( idVec3 &dir ) const {
   4358 	if ( fl.useContactMotorDir ) {
   4359 		dir = contactMotorDir * current->worldAxis;
   4360 		return true;
   4361 	}
   4362 	return false;
   4363 }
   4364 
   4365 /*
   4366 ================
   4367 idAFBody::GetPointVelocity
   4368 ================
   4369 */
   4370 idVec3 idAFBody::GetPointVelocity( const idVec3 &point ) const {
   4371 	idVec3 r = point - current->worldOrigin;
   4372 	return current->spatialVelocity.SubVec3(0) + current->spatialVelocity.SubVec3(1).Cross( r );
   4373 }
   4374 
   4375 /*
   4376 ================
   4377 idAFBody::AddForce
   4378 ================
   4379 */
   4380 void idAFBody::AddForce( const idVec3 &point, const idVec3 &force ) {
   4381 	current->externalForce.SubVec3(0) += force;
   4382 	current->externalForce.SubVec3(1) += (point - current->worldOrigin).Cross( force );
   4383 }
   4384 
   4385 /*
   4386 ================
   4387 idAFBody::InverseWorldSpatialInertiaMultiply
   4388 
   4389   dst = this->inverseWorldSpatialInertia * v;
   4390 ================
   4391 */
   4392 ID_INLINE void idAFBody::InverseWorldSpatialInertiaMultiply( idVecX &dst, const float *v ) const {
   4393 	const float *mPtr = inverseWorldSpatialInertia.ToFloatPtr();
   4394 	const float *vPtr = v;
   4395 	float *dstPtr = dst.ToFloatPtr();
   4396 
   4397 	if ( fl.spatialInertiaSparse ) {
   4398 		dstPtr[0] = mPtr[0*6+0] * vPtr[0];
   4399 		dstPtr[1] = mPtr[1*6+1] * vPtr[1];
   4400 		dstPtr[2] = mPtr[2*6+2] * vPtr[2];
   4401 		dstPtr[3] = mPtr[3*6+3] * vPtr[3] + mPtr[3*6+4] * vPtr[4] + mPtr[3*6+5] * vPtr[5];
   4402 		dstPtr[4] = mPtr[4*6+3] * vPtr[3] + mPtr[4*6+4] * vPtr[4] + mPtr[4*6+5] * vPtr[5];
   4403 		dstPtr[5] = mPtr[5*6+3] * vPtr[3] + mPtr[5*6+4] * vPtr[4] + mPtr[5*6+5] * vPtr[5];
   4404 	} else {
   4405 		gameLocal.Warning( "spatial inertia is not sparse for body %s", name.c_str() );
   4406 	}
   4407 }
   4408 
   4409 /*
   4410 ================
   4411 idAFBody::Save
   4412 ================
   4413 */
   4414 void idAFBody::Save( idSaveGame *saveFile ) {
   4415 	saveFile->WriteFloat( linearFriction );
   4416 	saveFile->WriteFloat( angularFriction );
   4417 	saveFile->WriteFloat( contactFriction );
   4418 	saveFile->WriteFloat( bouncyness );
   4419 	saveFile->WriteInt( clipMask );
   4420 	saveFile->WriteVec3( frictionDir );
   4421 	saveFile->WriteVec3( contactMotorDir );
   4422 	saveFile->WriteFloat( contactMotorVelocity );
   4423 	saveFile->WriteFloat( contactMotorForce );
   4424 
   4425 	saveFile->WriteFloat( mass );
   4426 	saveFile->WriteFloat( invMass );
   4427 	saveFile->WriteVec3( centerOfMass );
   4428 	saveFile->WriteMat3( inertiaTensor );
   4429 	saveFile->WriteMat3( inverseInertiaTensor );
   4430 
   4431 	saveFile->WriteVec3( current->worldOrigin );
   4432 	saveFile->WriteMat3( current->worldAxis );
   4433 	saveFile->WriteVec6( current->spatialVelocity );
   4434 	saveFile->WriteVec6( current->externalForce );
   4435 	saveFile->WriteVec3( atRestOrigin );
   4436 	saveFile->WriteMat3( atRestAxis );
   4437 }
   4438 
   4439 /*
   4440 ================
   4441 idAFBody::Restore
   4442 ================
   4443 */
   4444 void idAFBody::Restore( idRestoreGame *saveFile ) {
   4445 	saveFile->ReadFloat( linearFriction );
   4446 	saveFile->ReadFloat( angularFriction );
   4447 	saveFile->ReadFloat( contactFriction );
   4448 	saveFile->ReadFloat( bouncyness );
   4449 	saveFile->ReadInt( clipMask );
   4450 	saveFile->ReadVec3( frictionDir );
   4451 	saveFile->ReadVec3( contactMotorDir );
   4452 	saveFile->ReadFloat( contactMotorVelocity );
   4453 	saveFile->ReadFloat( contactMotorForce );
   4454 
   4455 	saveFile->ReadFloat( mass );
   4456 	saveFile->ReadFloat( invMass );
   4457 	saveFile->ReadVec3( centerOfMass );
   4458 	saveFile->ReadMat3( inertiaTensor );
   4459 	saveFile->ReadMat3( inverseInertiaTensor );
   4460 
   4461 	saveFile->ReadVec3( current->worldOrigin );
   4462 	saveFile->ReadMat3( current->worldAxis );
   4463 	saveFile->ReadVec6( current->spatialVelocity );
   4464 	saveFile->ReadVec6( current->externalForce );
   4465 	saveFile->ReadVec3( atRestOrigin );
   4466 	saveFile->ReadMat3( atRestAxis );
   4467 }
   4468 
   4469 
   4470 
   4471 //===============================================================
   4472 //                                                        M
   4473 //  idAFTree                                             MrE
   4474 //                                                        E
   4475 //===============================================================
   4476 
   4477 /*
   4478 ================
   4479 idAFTree::Factor
   4480 
   4481   factor matrix for the primary constraints in the tree
   4482 ================
   4483 */
   4484 void idAFTree::Factor() const {
   4485 	int i, j;
   4486 	idAFBody *body;
   4487 	idAFConstraint *child = NULL;
   4488 	idMatX childI;
   4489 
   4490 	childI.SetData( 6, 6, MATX_ALLOCA( 6 * 6 ) );
   4491 
   4492 	// from the leaves up towards the root
   4493 	for ( i = sortedBodies.Num() - 1; i >= 0; i-- ) {
   4494 		body = sortedBodies[i];
   4495 
   4496 		if ( body->children.Num() ) {
   4497 
   4498 			for ( j = 0; j < body->children.Num(); j++ ) {
   4499 
   4500 				child = body->children[j]->primaryConstraint;
   4501 
   4502 				// child->I = - child->body1->J.Transpose() * child->body1->I * child->body1->J;
   4503 				childI.SetSize( child->J1.GetNumRows(), child->J1.GetNumRows() );
   4504 				child->body1->J.TransposeMultiply( child->body1->I ).Multiply( childI, child->body1->J );
   4505 				childI.Negate();
   4506 
   4507 				child->invI = childI;
   4508 				if ( !child->invI.InverseFastSelf() ) {
   4509 					gameLocal.Warning( "idAFTree::Factor: couldn't invert %dx%d matrix for constraint '%s'",
   4510 									child->invI.GetNumRows(), child->invI.GetNumColumns(), child->GetName().c_str() );
   4511 				}
   4512 				child->J = child->invI * child->J;
   4513 
   4514 				body->I -= child->J.TransposeMultiply( childI ) * child->J;
   4515 			}
   4516 
   4517 			body->invI = body->I;
   4518 			if ( !body->invI.InverseFastSelf() && child != NULL ) {
   4519 				gameLocal.Warning( "idAFTree::Factor: couldn't invert %dx%d matrix for body %s",
   4520 								child->invI.GetNumRows(), child->invI.GetNumColumns(), body->GetName().c_str() );
   4521 			}
   4522 			if ( body->primaryConstraint ) {
   4523 				body->J = body->invI * body->J;
   4524 			}
   4525 		}
   4526 		else if ( body->primaryConstraint ) {
   4527 			body->J = body->inverseWorldSpatialInertia * body->J;
   4528 		}
   4529 	}
   4530 }
   4531 
   4532 /*
   4533 ================
   4534 idAFTree::Solve
   4535 
   4536   solve for primary constraints in the tree
   4537 ================
   4538 */
   4539 void idAFTree::Solve( int auxiliaryIndex ) const {
   4540 	int i, j;
   4541 	idAFBody *body, *child;
   4542 	idAFConstraint *primaryConstraint;
   4543 
   4544 	// from the leaves up towards the root
   4545 	for ( i = sortedBodies.Num() - 1; i >= 0; i-- ) {
   4546 		body = sortedBodies[i];
   4547 
   4548 		for ( j = 0; j < body->children.Num(); j++ ) {
   4549 			child = body->children[j];
   4550 			primaryConstraint = child->primaryConstraint;
   4551 
   4552 			if ( !child->fl.isZero ) {
   4553 				child->J.TransposeMultiplySub( primaryConstraint->s, child->s );
   4554 				primaryConstraint->fl.isZero = false;
   4555 			}
   4556 			if ( !primaryConstraint->fl.isZero ) {
   4557 				primaryConstraint->J.TransposeMultiplySub( body->s, primaryConstraint->s );
   4558 				body->fl.isZero = false;
   4559 			}
   4560 		}
   4561 	}
   4562 
   4563 	bool useSymmetry = af_useSymmetry.GetBool();
   4564 
   4565 	// from the root down towards the leaves
   4566 	for ( i = 0; i < sortedBodies.Num(); i++ ) {
   4567 		body = sortedBodies[i];
   4568 		primaryConstraint = body->primaryConstraint;
   4569 
   4570 		if ( primaryConstraint ) {
   4571 
   4572 			if ( useSymmetry && body->parent->maxSubTreeAuxiliaryIndex < auxiliaryIndex ) {
   4573 				continue;
   4574 			}
   4575 
   4576 			if ( !primaryConstraint->fl.isZero ) {
   4577 				primaryConstraint->s = primaryConstraint->invI * primaryConstraint->s;
   4578 			}
   4579 			primaryConstraint->J.MultiplySub( primaryConstraint->s, primaryConstraint->body2->s );
   4580 
   4581 			primaryConstraint->lm = primaryConstraint->s;
   4582 
   4583 			if ( useSymmetry && body->maxSubTreeAuxiliaryIndex < auxiliaryIndex ) {
   4584 				continue;
   4585 			}
   4586 
   4587 			if ( body->children.Num() ) {
   4588 				if ( !body->fl.isZero ) {
   4589 					body->s = body->invI * body->s;
   4590 				}
   4591 				body->J.MultiplySub( body->s, primaryConstraint->s );
   4592 			}
   4593 		} else if ( body->children.Num() ) {
   4594 			body->s = body->invI * body->s;
   4595 		}
   4596 	}
   4597 }
   4598 
   4599 /*
   4600 ================
   4601 idAFTree::Response
   4602 
   4603   calculate body forces in the tree in response to a constraint force
   4604 ================
   4605 */
   4606 void idAFTree::Response( const idAFConstraint *constraint, int row, int auxiliaryIndex ) const {
   4607 	int i, j;
   4608 	idAFBody *body;
   4609 	idAFConstraint *child, *primaryConstraint;
   4610 	idVecX v;
   4611 
   4612 	// if a single body don't waste time because there aren't any primary constraints
   4613 	if ( sortedBodies.Num() == 1 ) {
   4614 		body = constraint->body1;
   4615 		if ( body->tree == this ) {
   4616 			body->GetResponseForce( body->numResponses ) = constraint->J1.SubVec6( row );
   4617 			body->responseIndex[body->numResponses++] = auxiliaryIndex;
   4618 		}
   4619 		else {
   4620 			body = constraint->body2;
   4621 			body->GetResponseForce( body->numResponses ) = constraint->J2.SubVec6( row );
   4622 			body->responseIndex[body->numResponses++] = auxiliaryIndex;
   4623 		}
   4624 		return;
   4625 	}
   4626 
   4627 	v.SetData( 6, VECX_ALLOCA( 6 ) );
   4628 
   4629 	// initialize right hand side to zero
   4630 	for ( i = 0; i < sortedBodies.Num(); i++ ) {
   4631 		body = sortedBodies[i];
   4632 		primaryConstraint = body->primaryConstraint;
   4633 		if ( primaryConstraint ) {
   4634 			primaryConstraint->s.Zero();
   4635 			primaryConstraint->fl.isZero = true;
   4636 		}
   4637 		body->s.Zero();
   4638 		body->fl.isZero = true;
   4639 		body->GetResponseForce( body->numResponses ).Zero();
   4640 	}
   4641 
   4642 	// set right hand side for first constrained body
   4643 	body = constraint->body1;
   4644 	if ( body->tree == this ) {
   4645 		body->InverseWorldSpatialInertiaMultiply( v, constraint->J1[row] );
   4646 		primaryConstraint = body->primaryConstraint;
   4647 		if ( primaryConstraint ) {
   4648 			primaryConstraint->J1.Multiply( primaryConstraint->s, v );
   4649 			primaryConstraint->fl.isZero = false;
   4650 		}
   4651 		for ( i = 0; i < body->children.Num(); i++ ) {
   4652 			child = body->children[i]->primaryConstraint;
   4653 			child->J2.Multiply( child->s, v );
   4654 			child->fl.isZero = false;
   4655 		}
   4656 		body->GetResponseForce( body->numResponses ) = constraint->J1.SubVec6( row );
   4657 	}
   4658 
   4659 	// set right hand side for second constrained body
   4660 	body = constraint->body2;
   4661 	if ( body && body->tree == this ) {
   4662 		body->InverseWorldSpatialInertiaMultiply( v, constraint->J2[row] );
   4663 		primaryConstraint = body->primaryConstraint;
   4664 		if ( primaryConstraint ) {
   4665 			primaryConstraint->J1.MultiplyAdd( primaryConstraint->s, v );
   4666 			primaryConstraint->fl.isZero = false;
   4667 		}
   4668 		for ( i = 0; i < body->children.Num(); i++ ) {
   4669 			child = body->children[i]->primaryConstraint;
   4670 			child->J2.MultiplyAdd( child->s, v );
   4671 			child->fl.isZero = false;
   4672 		}
   4673 		body->GetResponseForce( body->numResponses ) = constraint->J2.SubVec6( row );
   4674 	}
   4675 
   4676 
   4677 	// solve for primary constraints
   4678 	Solve( auxiliaryIndex );
   4679 
   4680 	bool useSymmetry = af_useSymmetry.GetBool();
   4681 
   4682 	// store body forces in response to the constraint force
   4683 	idVecX force;
   4684 	for ( i = 0; i < sortedBodies.Num(); i++ ) {
   4685 		body = sortedBodies[i];
   4686 
   4687 		if ( useSymmetry && body->maxAuxiliaryIndex < auxiliaryIndex ) {
   4688 			continue;
   4689 		}
   4690 
   4691 		force.SetData( 6, body->response + body->numResponses * 8 );
   4692 
   4693 		// add forces of all primary constraints acting on this body
   4694 		primaryConstraint = body->primaryConstraint;
   4695 		if ( primaryConstraint ) {
   4696 			primaryConstraint->J1.TransposeMultiplyAdd( force, primaryConstraint->lm );
   4697 		}
   4698 		for ( j = 0; j < body->children.Num(); j++ ) {
   4699 			child = body->children[j]->primaryConstraint;
   4700 			child->J2.TransposeMultiplyAdd( force, child->lm );
   4701 		}
   4702 
   4703 		body->responseIndex[body->numResponses++] = auxiliaryIndex;
   4704 	}
   4705 }
   4706 
   4707 /*
   4708 ================
   4709 idAFTree::CalculateForces
   4710 
   4711   calculate forces on the bodies in the tree
   4712 ================
   4713 */
   4714 void idAFTree::CalculateForces( float timeStep ) const {
   4715 	int i, j;
   4716 	float invStep;
   4717 	idAFBody *body;
   4718 	idAFConstraint *child, *c, *primaryConstraint;
   4719 
   4720 	// forces on bodies
   4721 	for ( i = 0; i < sortedBodies.Num(); i++ ) {
   4722 		body = sortedBodies[i];
   4723 
   4724 		body->totalForce.SubVec6(0) = body->current->externalForce + body->auxForce.SubVec6(0);
   4725 	}
   4726 
   4727 	// if a single body don't waste time because there aren't any primary constraints
   4728 	if ( sortedBodies.Num() == 1 ) {
   4729 		return;
   4730 	}
   4731 
   4732 	invStep = 1.0f / timeStep;
   4733 
   4734 	// initialize right hand side
   4735 	for ( i = 0; i < sortedBodies.Num(); i++ ) {
   4736 		body = sortedBodies[i];
   4737 
   4738 		body->InverseWorldSpatialInertiaMultiply( body->acceleration, body->totalForce.ToFloatPtr() );
   4739 		body->acceleration.SubVec6(0) += body->current->spatialVelocity * invStep;
   4740 		primaryConstraint = body->primaryConstraint;
   4741 		if ( primaryConstraint ) {
   4742 			// b = ( J * acc + c )
   4743 			c = primaryConstraint;
   4744 			c->s = c->J1 * c->body1->acceleration + c->J2 * c->body2->acceleration + invStep * ( c->c1 + c->c2 );
   4745 			c->fl.isZero = false;
   4746 		}
   4747 		body->s.Zero();
   4748 		body->fl.isZero = true;
   4749 	}
   4750 
   4751 	// solve for primary constraints
   4752 	Solve();
   4753 
   4754 	// calculate forces on bodies after applying primary constraints
   4755 	for ( i = 0; i < sortedBodies.Num(); i++ ) {
   4756 		body = sortedBodies[i];
   4757 
   4758 		// add forces of all primary constraints acting on this body
   4759 		primaryConstraint = body->primaryConstraint;
   4760 		if ( primaryConstraint ) {
   4761 			primaryConstraint->J1.TransposeMultiplyAdd( body->totalForce, primaryConstraint->lm );
   4762 		}
   4763 		for ( j = 0; j < body->children.Num(); j++ ) {
   4764 			child = body->children[j]->primaryConstraint;
   4765 			child->J2.TransposeMultiplyAdd( body->totalForce, child->lm );
   4766 		}
   4767 	}
   4768 }
   4769 
   4770 /*
   4771 ================
   4772 idAFTree::SetMaxSubTreeAuxiliaryIndex
   4773 ================
   4774 */
   4775 void idAFTree::SetMaxSubTreeAuxiliaryIndex() {
   4776 	int i, j;
   4777 	idAFBody *body, *child;
   4778 
   4779 	// from the leaves up towards the root
   4780 	for ( i = sortedBodies.Num() - 1; i >= 0; i-- ) {
   4781 		body = sortedBodies[i];
   4782 
   4783 		body->maxSubTreeAuxiliaryIndex = body->maxAuxiliaryIndex;
   4784 		for ( j = 0; j < body->children.Num(); j++ ) {
   4785 			child = body->children[j];
   4786 			if ( child->maxSubTreeAuxiliaryIndex > body->maxSubTreeAuxiliaryIndex ) {
   4787 				body->maxSubTreeAuxiliaryIndex = child->maxSubTreeAuxiliaryIndex;
   4788 			}
   4789 		}
   4790 	}
   4791 }
   4792 
   4793 /*
   4794 ================
   4795 idAFTree::SortBodies_r
   4796 ================
   4797 */
   4798 void idAFTree::SortBodies_r( idList<idAFBody*>&sortedList, idAFBody *body ) {
   4799 	int i;
   4800 
   4801 	for ( i = 0; i < body->children.Num(); i++ ) {
   4802 		sortedList.Append( body->children[i] );
   4803 	}
   4804 	for ( i = 0; i < body->children.Num(); i++ ) {
   4805 		SortBodies_r( sortedList, body->children[i] );
   4806 	}
   4807 }
   4808 
   4809 /*
   4810 ================
   4811 idAFTree::SortBodies
   4812 
   4813   sort body list to make sure parents come first
   4814 ================
   4815 */
   4816 void idAFTree::SortBodies() {
   4817 	int i;
   4818 	idAFBody *body;
   4819 
   4820 	// find the root
   4821 	for ( i = 0; i < sortedBodies.Num(); i++ ) {
   4822 		if ( !sortedBodies[i]->parent ) {
   4823 			break;
   4824 		}
   4825 	}
   4826 
   4827 	if ( i >= sortedBodies.Num() ) {
   4828 		gameLocal.Error( "Articulated figure tree has no root." );
   4829 	}
   4830 
   4831 	body = sortedBodies[i];
   4832 	sortedBodies.Clear();
   4833 	sortedBodies.Append( body );
   4834 	SortBodies_r( sortedBodies, body );
   4835 }
   4836 
   4837 /*
   4838 ================
   4839 idAFTree::DebugDraw
   4840 ================
   4841 */
   4842 void idAFTree::DebugDraw( const idVec4 &color ) const {
   4843 	int i;
   4844 	idAFBody *body;
   4845 
   4846 	for ( i = 1; i < sortedBodies.Num(); i++ ) {
   4847 		body = sortedBodies[i];
   4848 		gameRenderWorld->DebugArrow( color, body->parent->current->worldOrigin, body->current->worldOrigin, 1 );
   4849 	}
   4850 }
   4851 
   4852 
   4853 //===============================================================
   4854 //                                                        M
   4855 //  idPhysics_AF                                         MrE
   4856 //                                                        E
   4857 //===============================================================
   4858 
   4859 /*
   4860 ================
   4861 idPhysics_AF::EvaluateConstraints
   4862 ================
   4863 */
   4864 void idPhysics_AF::EvaluateConstraints( float timeStep ) {
   4865 	int i;
   4866 	float invTimeStep;
   4867 	idAFBody *body;
   4868 	idAFConstraint *c;
   4869 
   4870 	invTimeStep = 1.0f / timeStep;
   4871 
   4872 	// setup the constraint equations for the current position and orientation of the bodies
   4873 	for ( i = 0; i < primaryConstraints.Num(); i++ ) {
   4874 		c = primaryConstraints[i];
   4875 		c->Evaluate( invTimeStep );
   4876 		c->J = c->J2;
   4877 	}
   4878 	for ( i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   4879 		auxiliaryConstraints[i]->Evaluate( invTimeStep );
   4880 	}
   4881 
   4882 	// add contact constraints to the list with frame constraints
   4883 	for ( i = 0; i < contactConstraints.Num(); i++ ) {
   4884 		AddFrameConstraint( contactConstraints[i] );
   4885 	}
   4886 
   4887 	// setup body primary constraint matrix
   4888 	for ( i = 0; i < bodies.Num(); i++ ) {
   4889 		body = bodies[i];
   4890 
   4891 		if ( body->primaryConstraint ) {
   4892 			body->J = body->primaryConstraint->J1.Transpose();
   4893 		}
   4894 	}
   4895 }
   4896 
   4897 /*
   4898 ================
   4899 idPhysics_AF::EvaluateBodies
   4900 ================
   4901 */
   4902 void idPhysics_AF::EvaluateBodies( float timeStep ) {
   4903 	int i;
   4904 	idAFBody *body;
   4905 	idMat3 axis;
   4906 
   4907 	for ( i = 0; i < bodies.Num(); i++ ) {
   4908 		body = bodies[i];
   4909 
   4910 		// we transpose the axis before using it because idMat3 is column-major
   4911 		axis = body->current->worldAxis.Transpose();
   4912 
   4913 		// if the center of mass is at the body point of reference
   4914 		if ( body->centerOfMass.Compare( vec3_origin, CENTER_OF_MASS_EPSILON ) ) {
   4915 
   4916 			// spatial inertia in world space
   4917 			body->I.Set( body->mass * mat3_identity, mat3_zero,
   4918 							mat3_zero, axis * body->inertiaTensor * axis.Transpose() );
   4919 
   4920 			// inverse spatial inertia in world space
   4921 			body->inverseWorldSpatialInertia.Set( body->invMass * mat3_identity, mat3_zero,
   4922 											mat3_zero, axis * body->inverseInertiaTensor * axis.Transpose() );
   4923 
   4924 			body->fl.spatialInertiaSparse = true;
   4925 		}
   4926 		else {
   4927 			idMat3 massMoment = body->mass * SkewSymmetric( body->centerOfMass );
   4928 
   4929 			// spatial inertia in world space
   4930 			body->I.Set( body->mass * mat3_identity, massMoment,
   4931 								massMoment.Transpose(), axis * body->inertiaTensor * axis.Transpose() );
   4932 
   4933 			// inverse spatial inertia in world space
   4934 			body->inverseWorldSpatialInertia = body->I.InverseFast();
   4935 
   4936 			body->fl.spatialInertiaSparse = false;
   4937 		}
   4938 
   4939 		// initialize auxiliary constraint force to zero
   4940 		body->auxForce.Zero();
   4941 	}
   4942 }
   4943 
   4944 /*
   4945 ================
   4946 idPhysics_AF::AddFrameConstraints
   4947 ================
   4948 */
   4949 void idPhysics_AF::AddFrameConstraints() {
   4950 	int i;
   4951 
   4952 	// add frame constraints to auxiliary constraints
   4953 	for ( i = 0; i < frameConstraints.Num(); i++ ) {
   4954 		auxiliaryConstraints.Append( frameConstraints[i] );
   4955 	}
   4956 }
   4957 
   4958 /*
   4959 ================
   4960 idPhysics_AF::RemoveFrameConstraints
   4961 ================
   4962 */
   4963 void idPhysics_AF::RemoveFrameConstraints() {
   4964 	// remove all the frame constraints from the auxiliary constraints
   4965 	auxiliaryConstraints.SetNum( auxiliaryConstraints.Num() - frameConstraints.Num() );
   4966 	frameConstraints.SetNum( 0 );
   4967 }
   4968 
   4969 /*
   4970 ================
   4971 idPhysics_AF::ApplyFriction
   4972 ================
   4973 */
   4974 void idPhysics_AF::ApplyFriction( float timeStep, float endTimeMSec ) {
   4975 	int i;
   4976 	float invTimeStep;
   4977 
   4978 	if ( af_skipFriction.GetBool() ) {
   4979 		return;
   4980 	}
   4981 
   4982 	if ( jointFrictionDentStart < MS2SEC( endTimeMSec ) && jointFrictionDentEnd > MS2SEC( endTimeMSec ) ) {
   4983 		float halfTime = ( jointFrictionDentEnd - jointFrictionDentStart ) * 0.5f;
   4984 		if ( jointFrictionDentStart + halfTime > MS2SEC( endTimeMSec ) ) {
   4985 			jointFrictionDentScale = 1.0f - ( 1.0f - jointFrictionDent ) * ( MS2SEC( endTimeMSec ) - jointFrictionDentStart ) / halfTime;
   4986 		} else {
   4987 			jointFrictionDentScale = jointFrictionDent + ( 1.0f - jointFrictionDent ) * ( MS2SEC( endTimeMSec ) - jointFrictionDentStart - halfTime ) / halfTime;
   4988 		}
   4989 	} else {
   4990 		jointFrictionDentScale = 0.0f;
   4991 	}
   4992 
   4993 	if ( contactFrictionDentStart < MS2SEC( endTimeMSec ) && contactFrictionDentEnd > MS2SEC( endTimeMSec ) ) {
   4994 		float halfTime = ( contactFrictionDentEnd - contactFrictionDentStart ) * 0.5f;
   4995 		if ( contactFrictionDentStart + halfTime > MS2SEC( endTimeMSec ) ) {
   4996 			contactFrictionDentScale = 1.0f - ( 1.0f - contactFrictionDent ) * ( MS2SEC( endTimeMSec ) - contactFrictionDentStart ) / halfTime;
   4997 		} else {
   4998 			contactFrictionDentScale = contactFrictionDent + ( 1.0f - contactFrictionDent ) * ( MS2SEC( endTimeMSec ) - contactFrictionDentStart - halfTime ) / halfTime;
   4999 		}
   5000 	} else {
   5001 		contactFrictionDentScale = 0.0f;
   5002 	}
   5003 
   5004 	invTimeStep = 1.0f / timeStep;
   5005 
   5006 	for ( i = 0; i < primaryConstraints.Num(); i++ ) {
   5007 		primaryConstraints[i]->ApplyFriction( invTimeStep );
   5008 	}
   5009 	for ( i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   5010 		auxiliaryConstraints[i]->ApplyFriction( invTimeStep );
   5011 	}
   5012 	for ( i = 0; i < frameConstraints.Num(); i++ ) {
   5013 		frameConstraints[i]->ApplyFriction( invTimeStep );
   5014 	}
   5015 }
   5016 
   5017 /*
   5018 ================
   5019 idPhysics_AF::PrimaryFactor
   5020 ================
   5021 */
   5022 void idPhysics_AF::PrimaryFactor() {
   5023 	int i;
   5024 
   5025 	for ( i = 0; i < trees.Num(); i++ ) {
   5026 		trees[i]->Factor();
   5027 	}
   5028 }
   5029 
   5030 /*
   5031 ================
   5032 idPhysics_AF::PrimaryForces
   5033 ================
   5034 */
   5035 void idPhysics_AF::PrimaryForces( float timeStep ) {
   5036 	int i;
   5037 
   5038 	for ( i = 0; i < trees.Num(); i++ ) {
   5039 		trees[i]->CalculateForces( timeStep );
   5040 	}
   5041 }
   5042 
   5043 /*
   5044 ================
   5045 idPhysics_AF::AuxiliaryForces
   5046 ================
   5047 */
   5048 void idPhysics_AF::AuxiliaryForces( float timeStep ) {
   5049 	int i, j, k, l, n, m, s, numAuxConstraints, *index, *boxIndex;
   5050 	float *ptr, *j1, *j2, *dstPtr, *forcePtr;
   5051 	float invStep, u;
   5052 	idAFBody *body;
   5053 	idAFConstraint *constraint;
   5054 	idVecX tmp;
   5055 	idMatX jmk;
   5056 	idVecX rhs, w, lm, lo, hi;
   5057 
   5058 	// get the number of one dimensional auxiliary constraints
   5059 	for ( numAuxConstraints = 0, i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   5060 		numAuxConstraints += auxiliaryConstraints[i]->J1.GetNumRows();
   5061 	}
   5062 
   5063 	if ( numAuxConstraints == 0 ) {
   5064 		return;
   5065 	}
   5066 
   5067 	// allocate memory to store the body response to auxiliary constraint forces
   5068 	forcePtr = (float *) _alloca16( bodies.Num() * numAuxConstraints * 8 * sizeof( float ) );
   5069 	index = (int *) _alloca16( bodies.Num() * numAuxConstraints * sizeof( int ) );
   5070 	for ( i = 0; i < bodies.Num(); i++ ) {
   5071 		body = bodies[i];
   5072 		body->response = forcePtr;
   5073 		body->responseIndex = index;
   5074 		body->numResponses = 0;
   5075 		body->maxAuxiliaryIndex = 0;
   5076 		forcePtr += numAuxConstraints * 8;
   5077 		index += numAuxConstraints;
   5078 	}
   5079 
   5080 	// set on each body the largest index of an auxiliary constraint constraining the body
   5081 	if ( af_useSymmetry.GetBool() ) {
   5082 		for ( k = 0, i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   5083 			constraint = auxiliaryConstraints[i];
   5084 			for ( j = 0; j < constraint->J1.GetNumRows(); j++, k++ ) {
   5085 				if ( k > constraint->body1->maxAuxiliaryIndex ) {
   5086 					constraint->body1->maxAuxiliaryIndex = k;
   5087 				}
   5088 				if ( constraint->body2 && k > constraint->body2->maxAuxiliaryIndex ) {
   5089 					constraint->body2->maxAuxiliaryIndex = k;
   5090 				}
   5091 			}
   5092 		}
   5093 		for ( i = 0; i < trees.Num(); i++ ) {
   5094 			trees[i]->SetMaxSubTreeAuxiliaryIndex();
   5095 		}
   5096 	}
   5097 
   5098 	// calculate forces of primary constraints in response to the auxiliary constraint forces
   5099 	for ( k = 0, i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   5100 		constraint = auxiliaryConstraints[i];
   5101 
   5102 		for ( j = 0; j < constraint->J1.GetNumRows(); j++, k++ ) {
   5103 
   5104 			// calculate body forces in the tree in response to the constraint force
   5105 			constraint->body1->tree->Response( constraint, j, k );
   5106 			// if there is a second body which is part of a different tree
   5107 			if ( constraint->body2 && constraint->body2->tree != constraint->body1->tree ) {
   5108 				// calculate body forces in the second tree in response to the constraint force
   5109 				constraint->body2->tree->Response( constraint, j, k );
   5110 			}
   5111 		}
   5112 	}
   5113 
   5114 	// NOTE: the rows are 16 byte padded
   5115 	jmk.SetData( numAuxConstraints, ((numAuxConstraints+3)&~3), MATX_ALLOCA( numAuxConstraints * ((numAuxConstraints+3)&~3) ) );
   5116 	tmp.SetData( 6, VECX_ALLOCA( 6 ) );
   5117 
   5118 	// create constraint matrix for auxiliary constraints using a mass matrix adjusted for the primary constraints
   5119 	for ( k = 0, i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   5120 		constraint = auxiliaryConstraints[i];
   5121 
   5122 		for ( j = 0; j < constraint->J1.GetNumRows(); j++, k++ ) {
   5123 			constraint->body1->InverseWorldSpatialInertiaMultiply( tmp, constraint->J1[j] );
   5124 			j1 = tmp.ToFloatPtr();
   5125 			ptr = constraint->body1->response;
   5126 			index = constraint->body1->responseIndex;
   5127 			dstPtr = jmk[k];
   5128 			s = af_useSymmetry.GetBool() ? k + 1 : numAuxConstraints;
   5129 			for ( l = n = 0, m = index[n]; n < constraint->body1->numResponses && m < s; n++, m = index[n] ) {
   5130 				while( l < m ) {
   5131 					dstPtr[l++] = 0.0f;
   5132 				}
   5133 				dstPtr[l++] = j1[0] * ptr[0] + j1[1] * ptr[1] + j1[2] * ptr[2] +
   5134 								j1[3] * ptr[3] + j1[4] * ptr[4] + j1[5] * ptr[5];
   5135 				ptr += 8;
   5136 			}
   5137 
   5138 			while( l < s ) {
   5139 				dstPtr[l++] = 0.0f;
   5140 			}
   5141 
   5142 			if ( constraint->body2 ) {
   5143 				constraint->body2->InverseWorldSpatialInertiaMultiply( tmp, constraint->J2[j] );
   5144 				j2 = tmp.ToFloatPtr();
   5145 				ptr = constraint->body2->response;
   5146 				index = constraint->body2->responseIndex;
   5147 				for ( n = 0, m = index[n]; n < constraint->body2->numResponses && m < s; n++, m = index[n] ) {
   5148 					dstPtr[m] += j2[0] * ptr[0] + j2[1] * ptr[1] + j2[2] * ptr[2] +
   5149 										j2[3] * ptr[3] + j2[4] * ptr[4] + j2[5] * ptr[5];
   5150 					ptr += 8;
   5151 				}
   5152 			}
   5153 		}
   5154 	}
   5155 
   5156 	if ( af_useSymmetry.GetBool() ) {
   5157 		n = jmk.GetNumColumns();
   5158 		for ( i = 0; i < numAuxConstraints; i++ ) {
   5159 			ptr = jmk.ToFloatPtr() + ( i + 1 ) * n + i;
   5160 			dstPtr = jmk.ToFloatPtr() + i * n + i + 1;
   5161 			for ( j = i+1; j < numAuxConstraints; j++ ) {
   5162 				*dstPtr++ = *ptr;
   5163 				ptr += n;
   5164 			}
   5165 		}
   5166 	}
   5167 
   5168 	invStep = 1.0f / timeStep;
   5169 
   5170 	// calculate body acceleration
   5171 	for ( i = 0; i < bodies.Num(); i++ ) {
   5172 		body = bodies[i];
   5173 		body->InverseWorldSpatialInertiaMultiply( body->acceleration, body->totalForce.ToFloatPtr() );
   5174 		body->acceleration.SubVec6(0) += body->current->spatialVelocity * invStep;
   5175 	}
   5176 
   5177 	rhs.SetData( numAuxConstraints, VECX_ALLOCA( numAuxConstraints ) );
   5178 	lo.SetData( numAuxConstraints, VECX_ALLOCA( numAuxConstraints ) );
   5179 	hi.SetData( numAuxConstraints, VECX_ALLOCA( numAuxConstraints ) );
   5180 	lm.SetData( numAuxConstraints, VECX_ALLOCA( numAuxConstraints ) );
   5181 	boxIndex = (int *) _alloca16( numAuxConstraints * sizeof( int ) );
   5182 
   5183 	// set first index for special box constrained variables
   5184 	for ( k = 0, i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   5185 		auxiliaryConstraints[i]->firstIndex = k;
   5186 		k += auxiliaryConstraints[i]->J1.GetNumRows();
   5187 	}
   5188 
   5189 	// initialize right hand side and low and high bounds for auxiliary constraints
   5190 	for ( k = 0, i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   5191 		constraint = auxiliaryConstraints[i];
   5192 		n = k;
   5193 
   5194 		for ( j = 0; j < constraint->J1.GetNumRows(); j++, k++ ) {
   5195 
   5196 			j1 = constraint->J1[j];
   5197 			ptr = constraint->body1->acceleration.ToFloatPtr();
   5198 			rhs[k] = j1[0] * ptr[0] + j1[1] * ptr[1] + j1[2] * ptr[2] + j1[3] * ptr[3] + j1[4] * ptr[4] + j1[5] * ptr[5];
   5199 			rhs[k] += constraint->c1[j] * invStep;
   5200 
   5201 			if ( constraint->body2 ) {
   5202 				j2 = constraint->J2[j];
   5203 				ptr = constraint->body2->acceleration.ToFloatPtr();
   5204 				rhs[k] += j2[0] * ptr[0] + j2[1] * ptr[1] + j2[2] * ptr[2] + j2[3] * ptr[3] + j2[4] * ptr[4] + j2[5] * ptr[5];
   5205 				rhs[k] += constraint->c2[j] * invStep;
   5206 			}
   5207 
   5208 			rhs[k] = -rhs[k];
   5209 			lo[k] = constraint->lo[j];
   5210 			hi[k] = constraint->hi[j];
   5211 
   5212 			if ( constraint->boxIndex[j] >= 0 ) {
   5213 				if ( constraint->boxConstraint->fl.isPrimary ) {
   5214 					gameLocal.Error( "cannot reference primary constraints for the box index" );
   5215 				}
   5216 				boxIndex[k] = constraint->boxConstraint->firstIndex + constraint->boxIndex[j];
   5217 			}
   5218 			else {
   5219 				boxIndex[k] = -1;
   5220 			}
   5221 			jmk[k][k] += constraint->e[j] * invStep;
   5222 		}
   5223 	}
   5224 
   5225 #ifdef AF_TIMINGS
   5226 	timer_lcp.Start();
   5227 #endif
   5228 
   5229 	// calculate lagrange multipliers for auxiliary constraints
   5230 	if ( !lcp->Solve( jmk, lm, rhs, lo, hi, boxIndex ) ) {
   5231 		return;		// bad monkey!
   5232 	}
   5233 
   5234 #ifdef AF_TIMINGS
   5235 	timer_lcp.Stop();
   5236 #endif
   5237 
   5238 	// calculate auxiliary constraint forces
   5239 	for ( k = 0, i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   5240 		constraint = auxiliaryConstraints[i];
   5241 
   5242 		for ( j = 0; j < constraint->J1.GetNumRows(); j++, k++ ) {
   5243 			constraint->lm[j] = u = lm[k];
   5244 
   5245 			j1 = constraint->J1[j];
   5246 			ptr = constraint->body1->auxForce.ToFloatPtr();
   5247 			ptr[0] += j1[0] * u; ptr[1] += j1[1] * u; ptr[2] += j1[2] * u;
   5248 			ptr[3] += j1[3] * u; ptr[4] += j1[4] * u; ptr[5] += j1[5] * u;
   5249 
   5250 			if ( constraint->body2 ) {
   5251 				j2 = constraint->J2[j];
   5252 				ptr = constraint->body2->auxForce.ToFloatPtr();
   5253 				ptr[0] += j2[0] * u; ptr[1] += j2[1] * u; ptr[2] += j2[2] * u;
   5254 				ptr[3] += j2[3] * u; ptr[4] += j2[4] * u; ptr[5] += j2[5] * u;
   5255 			}
   5256 		}
   5257 	}
   5258 
   5259 	// recalculate primary constraint forces in response to auxiliary constraint forces
   5260 	PrimaryForces( timeStep );
   5261 
   5262 	// clear pointers pointing to stack space so tools don't get confused
   5263 	for ( i = 0; i < bodies.Num(); i++ ) {
   5264 		body = bodies[i];
   5265 		body->response = NULL;
   5266 		body->responseIndex = NULL;
   5267 	}
   5268 }
   5269 
   5270 /*
   5271 ================
   5272 idPhysics_AF::VerifyContactConstraints
   5273 ================
   5274 */
   5275 void idPhysics_AF::VerifyContactConstraints() {
   5276 #if 0
   5277 	int i;
   5278 	float impulseNumerator, impulseDenominator;
   5279 	idVec3 r, velocity, normalVelocity, normal, impulse;
   5280 	idAFBody *body;
   5281 
   5282 	for ( i = 0; i < contactConstraints.Num(); i++ ) {
   5283 		body = contactConstraints[i]->body1;
   5284 		const contactInfo_t &contact = contactConstraints[i]->GetContact();
   5285 
   5286 		r = contact.point - body->GetCenterOfMass();
   5287 
   5288 		// calculate velocity at contact point
   5289 		velocity = body->GetLinearVelocity() + body->GetAngularVelocity().Cross( r );
   5290 
   5291 		// velocity along normal vector
   5292 		normalVelocity = ( velocity * contact.normal ) * contact.normal;
   5293 
   5294 		// if moving towards the surface at the contact point
   5295 		if ( normalVelocity * contact.normal < 0.0f ) {
   5296 			// calculate impulse
   5297 			normal = -normalVelocity;
   5298 			impulseNumerator = normal.Normalize();
   5299 			impulseDenominator = body->GetInverseMass() + ( ( body->GetInverseWorldInertia() * r.Cross( normal ) ).Cross( r ) * normal );
   5300 			impulse = (impulseNumerator / impulseDenominator) * normal * 1.0001f;
   5301 
   5302 			// apply impulse
   5303 			body->SetLinearVelocity( body->GetLinearVelocity() + impulse );
   5304 			body->SetAngularVelocity( body->GetAngularVelocity() + r.Cross( impulse ) );
   5305 		}
   5306 	}
   5307 #else
   5308 	int i;
   5309 	idAFBody *body;
   5310 	idVec3 normal;
   5311 
   5312 	for ( i = 0; i < contactConstraints.Num(); i++ ) {
   5313 		body = contactConstraints[i]->body1;
   5314 		normal = contactConstraints[i]->GetContact().normal;
   5315 		if ( normal * body->next->spatialVelocity.SubVec3(0) <= 0.0f ) {
   5316 			body->next->spatialVelocity.SubVec3(0) -= 1.0001f * (normal * body->next->spatialVelocity.SubVec3(0)) * normal;
   5317 		}
   5318 		body = contactConstraints[i]->body2;
   5319 		if ( !body ) {
   5320 			continue;
   5321 		}
   5322 		normal = -normal;
   5323 		if ( normal * body->next->spatialVelocity.SubVec3(0) <= 0.0f ) {
   5324 			body->next->spatialVelocity.SubVec3(0) -= 1.0001f * (normal * body->next->spatialVelocity.SubVec3(0)) * normal;
   5325 		}
   5326 	}
   5327 #endif
   5328 }
   5329 
   5330 /*
   5331 ================
   5332 idPhysics_AF::Evolve
   5333 ================
   5334 */
   5335 void idPhysics_AF::Evolve( float timeStep ) {
   5336 	int i;
   5337 	float angle;
   5338 	idVec3 vec;
   5339 	idAFBody *body;
   5340 	idVec6 force;
   5341 	idRotation rotation;
   5342 	float vSqr, maxLinearVelocity, maxAngularVelocity;
   5343 	
   5344 	maxLinearVelocity = af_maxLinearVelocity.GetFloat() / timeStep;
   5345 	maxAngularVelocity = af_maxAngularVelocity.GetFloat() / timeStep;
   5346 
   5347 	for ( i = 0; i < bodies.Num(); i++ ) {
   5348 		body = bodies[i];
   5349 
   5350 		// calculate the spatial velocity for the next physics state
   5351 		body->InverseWorldSpatialInertiaMultiply( body->acceleration, body->totalForce.ToFloatPtr() );
   5352 		body->next->spatialVelocity = body->current->spatialVelocity + timeStep * body->acceleration.SubVec6(0);
   5353 
   5354 		if ( maxLinearVelocity > 0.0f ) {
   5355 			// cap the linear velocity
   5356 			vSqr = body->next->spatialVelocity.SubVec3(0).LengthSqr();
   5357 			if ( vSqr > Square( maxLinearVelocity ) ) {
   5358 				body->next->spatialVelocity.SubVec3(0) *= idMath::InvSqrt( vSqr ) * maxLinearVelocity;
   5359 			}
   5360 		}
   5361 
   5362 		if ( maxAngularVelocity > 0.0f ) {
   5363 			// cap the angular velocity
   5364 			vSqr = body->next->spatialVelocity.SubVec3(1).LengthSqr();
   5365 			if ( vSqr > Square( maxAngularVelocity ) ) {
   5366 				body->next->spatialVelocity.SubVec3(1) *= idMath::InvSqrt( vSqr ) * maxAngularVelocity;
   5367 			}
   5368 		}
   5369 	}
   5370 
   5371 	// make absolutely sure all contact constraints are satisfied
   5372 	VerifyContactConstraints();
   5373 
   5374 	// calculate the position of the bodies for the next physics state
   5375 	for ( i = 0; i < bodies.Num(); i++ ) {
   5376 		body = bodies[i];
   5377 
   5378 		// translate world origin
   5379 		body->next->worldOrigin = body->current->worldOrigin + timeStep * body->next->spatialVelocity.SubVec3( 0 );
   5380 
   5381 		// convert angular velocity to a rotation matrix
   5382 		vec = body->next->spatialVelocity.SubVec3( 1 );
   5383 		angle = -timeStep * (float) RAD2DEG( vec.Normalize() );
   5384 		rotation = idRotation( vec3_origin, vec, angle );
   5385 		rotation.Normalize180();
   5386 
   5387 		// rotate world axis
   5388 		body->next->worldAxis = body->current->worldAxis * rotation.ToMat3();
   5389 		body->next->worldAxis.OrthoNormalizeSelf();
   5390 
   5391 		// linear and angular friction
   5392 		body->next->spatialVelocity.SubVec3(0) -= body->linearFriction * body->next->spatialVelocity.SubVec3(0);
   5393 		body->next->spatialVelocity.SubVec3(1) -= body->angularFriction * body->next->spatialVelocity.SubVec3(1);
   5394 	}
   5395 }
   5396 
   5397 /*
   5398 ================
   5399 idPhysics_AF::CollisionImpulse
   5400 
   5401   apply impulse to the colliding bodies
   5402   the current state of the body should be set to the moment of impact
   5403   this is silly as it doesn't take the AF structure into account
   5404 ================
   5405 */
   5406 bool idPhysics_AF::CollisionImpulse( float timeStep, idAFBody *body, trace_t &collision ) {
   5407 	idVec3 r, velocity, impulse;
   5408 	idMat3 inverseWorldInertiaTensor;
   5409 	float impulseNumerator, impulseDenominator;
   5410 	impactInfo_t info;
   5411 	idEntity *ent;
   5412 
   5413 	ent = gameLocal.entities[collision.c.entityNum];
   5414 	if ( ent == self ) {
   5415 		return false;
   5416 	}
   5417 
   5418 	// get info from other entity involved
   5419 	ent->GetImpactInfo( self, collision.c.id, collision.c.point, &info );
   5420 	// collision point relative to the body center of mass
   5421 	r = collision.c.point - (body->current->worldOrigin + body->centerOfMass * body->current->worldAxis);
   5422 	// the velocity at the collision point
   5423 	velocity = body->current->spatialVelocity.SubVec3(0) + body->current->spatialVelocity.SubVec3(1).Cross(r);
   5424 	// subtract velocity of other entity
   5425 	velocity -= info.velocity;
   5426 	// never stick
   5427 	if ( velocity * collision.c.normal > 0.0f ) {
   5428 		velocity = collision.c.normal;
   5429 	}
   5430 	inverseWorldInertiaTensor = body->current->worldAxis.Transpose() * body->inverseInertiaTensor * body->current->worldAxis;
   5431 	impulseNumerator = -( 1.0f + body->bouncyness ) * ( velocity * collision.c.normal );
   5432 	impulseDenominator = body->invMass + ( ( inverseWorldInertiaTensor * r.Cross( collision.c.normal ) ).Cross( r ) * collision.c.normal );
   5433 	if ( info.invMass ) {
   5434 		impulseDenominator += info.invMass + ( ( info.invInertiaTensor * info.position.Cross( collision.c.normal ) ).Cross( info.position ) * collision.c.normal );
   5435 	}
   5436 	impulse = (impulseNumerator / impulseDenominator) * collision.c.normal;
   5437 
   5438 	// apply impact to other entity
   5439 	ent->ApplyImpulse( self, collision.c.id, collision.c.point, -impulse );
   5440 
   5441 	// callback to self to let the entity know about the impact
   5442 	return self->Collide( collision, velocity );
   5443 }
   5444 
   5445 /*
   5446 ================
   5447 idPhysics_AF::ApplyCollisions
   5448 ================
   5449 */
   5450 bool idPhysics_AF::ApplyCollisions( float timeStep ) {
   5451 	int i;
   5452 
   5453 	for ( i = 0; i < collisions.Num(); i++ ) {
   5454 		if ( CollisionImpulse( timeStep, collisions[i].body, collisions[i].trace ) ) {
   5455 			return true;
   5456 		}
   5457 	}
   5458 	return false;
   5459 }
   5460 
   5461 /*
   5462 ================
   5463 idPhysics_AF::SetupCollisionForBody
   5464 ================
   5465 */
   5466 idEntity *idPhysics_AF::SetupCollisionForBody( idAFBody *body ) const {
   5467 	int i;
   5468 	idAFBody *b;
   5469 	idEntity *passEntity;
   5470 
   5471 	passEntity = NULL;
   5472 
   5473 	if ( !selfCollision || !body->fl.selfCollision || af_skipSelfCollision.GetBool() ) {
   5474 
   5475 		// disable all bodies
   5476 		for ( i = 0; i < bodies.Num(); i++ ) {
   5477 			bodies[i]->clipModel->Disable();
   5478 		}
   5479 
   5480 		// don't collide with world collision model if attached to the world
   5481 		for ( i = 0; i < body->constraints.Num(); i++ ) {
   5482 			if ( !body->constraints[i]->fl.noCollision ) {
   5483 				continue;
   5484 			}
   5485 			// if this constraint attaches the body to the world
   5486 			if ( body->constraints[i]->body2 == NULL ) {
   5487 				// don't collide with the world collision model
   5488 				passEntity = gameLocal.world;
   5489 			}
   5490 		}
   5491 
   5492 	} else {
   5493 
   5494 		// enable all bodies that have self collision
   5495 		for ( i = 0; i < bodies.Num(); i++ ) {
   5496 			if ( bodies[i]->fl.selfCollision ) {
   5497 				bodies[i]->clipModel->Enable();
   5498 			} else {
   5499 				bodies[i]->clipModel->Disable();
   5500 			}
   5501 		}
   5502 
   5503 		// don't let the body collide with itself
   5504 		body->clipModel->Disable();
   5505 
   5506 		// disable any bodies attached with constraints
   5507 		for ( i = 0; i < body->constraints.Num(); i++ ) {
   5508 			if ( !body->constraints[i]->fl.noCollision ) {
   5509 				continue;
   5510 			}
   5511 			// if this constraint attaches the body to the world
   5512 			if ( body->constraints[i]->body2 == NULL ) {
   5513 				// don't collide with the world collision model
   5514 				passEntity = gameLocal.world;
   5515 			} else {
   5516 				if ( body->constraints[i]->body1 == body ) {
   5517 					b = body->constraints[i]->body2;
   5518 				} else if ( body->constraints[i]->body2 == body ) {
   5519 					b = body->constraints[i]->body1;
   5520 				} else {
   5521 					continue;
   5522 				}
   5523 				// don't collide with this body
   5524 				b->clipModel->Disable();
   5525 			}
   5526 		}
   5527 	}
   5528 
   5529 	return passEntity;
   5530 }
   5531 
   5532 /*
   5533 ================
   5534 idPhysics_AF::CheckForCollisions
   5535 
   5536   check for collisions between the current and next state
   5537   if there is a collision the next state is set to the state at the moment of impact
   5538   assumes all bodies are linked for collision detection and relinks all bodies after moving them
   5539 ================
   5540 */
   5541 void idPhysics_AF::CheckForCollisions( float timeStep ) {
   5542 //	#define TEST_COLLISION_DETECTION
   5543 	int i, index;
   5544 	idAFBody *body;
   5545 	idMat3 axis;
   5546 	idRotation rotation;
   5547 	trace_t collision;
   5548 	idEntity *passEntity;
   5549 
   5550 	// clear list with collisions
   5551 	collisions.SetNum( 0 );
   5552 
   5553 	if ( !enableCollision ) {
   5554 		return;
   5555 	}
   5556 
   5557 	for ( i = 0; i < bodies.Num(); i++ ) {
   5558 		body = bodies[i];
   5559 
   5560 		if ( body->clipMask != 0 ) {
   5561 
   5562 			passEntity = SetupCollisionForBody( body );
   5563 
   5564 #ifdef TEST_COLLISION_DETECTION
   5565 			bool startsolid = false;
   5566 			if ( gameLocal.clip.Contents( body->current->worldOrigin, body->clipModel,
   5567 															body->current->worldAxis, body->clipMask, passEntity ) ) {
   5568 				startsolid = true;
   5569 			}
   5570 #endif
   5571 
   5572 			TransposeMultiply( body->current->worldAxis, body->next->worldAxis, axis );
   5573 			rotation = axis.ToRotation();
   5574 			rotation.SetOrigin( body->current->worldOrigin );
   5575 
   5576 			// if there was a collision
   5577 			if ( gameLocal.clip.Motion( collision, body->current->worldOrigin, body->next->worldOrigin, rotation,
   5578 										body->clipModel, body->current->worldAxis, body->clipMask, passEntity ) ) {
   5579 
   5580 				// set the next state to the state at the moment of impact
   5581 				body->next->worldOrigin = collision.endpos;
   5582 				body->next->worldAxis = collision.endAxis;
   5583 
   5584 				// add collision to the list
   5585 				index = collisions.Num();
   5586 				collisions.SetNum( index + 1 );
   5587 				collisions[index].trace = collision;
   5588 				collisions[index].body = body;
   5589 			}
   5590 
   5591 #ifdef TEST_COLLISION_DETECTION
   5592 			if ( gameLocal.clip.Contents( body->next->worldOrigin, body->clipModel,
   5593 														body->next->worldAxis, body->clipMask, passEntity ) ) {
   5594 				if ( !startsolid ) {
   5595 					int bah = 1;
   5596 				}
   5597 			}
   5598 #endif
   5599 		}
   5600 
   5601 		body->clipModel->Link( gameLocal.clip, self, body->clipModel->GetId(), body->next->worldOrigin, body->next->worldAxis );
   5602 	}
   5603 }
   5604 
   5605 /*
   5606 ================
   5607 idPhysics_AF::EvaluateContacts
   5608 ================
   5609 */
   5610 bool idPhysics_AF::EvaluateContacts() {
   5611 	int i, j, k, numContacts, numBodyContacts;
   5612 	idAFBody *body;
   5613 	contactInfo_t contactInfo[10];
   5614 	idEntity *passEntity;
   5615 	idVecX dir( 6, VECX_ALLOCA( 6 ) );
   5616 
   5617 	// evaluate bodies
   5618 	EvaluateBodies( current.lastTimeStep );
   5619 
   5620 	// remove all existing contacts
   5621 	ClearContacts();
   5622 
   5623 	contactBodies.SetNum( 0 );
   5624 
   5625 	if ( !enableCollision ) {
   5626 		return false;
   5627 	}
   5628 
   5629 	// find all the contacts
   5630 	for ( i = 0; i < bodies.Num(); i++ ) {
   5631 		body = bodies[i];
   5632 
   5633 		if ( body->clipMask == 0 ) {
   5634 			continue;
   5635 		}
   5636 
   5637 		passEntity = SetupCollisionForBody( body );
   5638 
   5639 		body->InverseWorldSpatialInertiaMultiply( dir, body->current->externalForce.ToFloatPtr() );
   5640 		dir.SubVec6(0) = body->current->spatialVelocity + current.lastTimeStep * dir.SubVec6(0);
   5641 		dir.SubVec3(0).Normalize();
   5642 		dir.SubVec3(1).Normalize();
   5643 
   5644 		numContacts = gameLocal.clip.Contacts( contactInfo, 10, body->current->worldOrigin, dir.SubVec6(0), 2.0f, //CONTACT_EPSILON,
   5645 						body->clipModel, body->current->worldAxis, body->clipMask, passEntity );
   5646 
   5647 #if 1
   5648 		// merge nearby contacts between the same bodies
   5649 		// and assure there are at most three planar contacts between any pair of bodies
   5650 		for ( j = 0; j < numContacts; j++ ) {
   5651 
   5652 			numBodyContacts = 0;
   5653 			for ( k = 0; k < contacts.Num(); k++ ) {
   5654 				if ( contacts[k].entityNum == contactInfo[j].entityNum ) {
   5655 					if ( ( contacts[k].id == i && contactInfo[j].id == contactBodies[k] ) ||
   5656 							( contactBodies[k] == i && contacts[k].id == contactInfo[j].id ) ) {
   5657 
   5658 						if ( ( contacts[k].point - contactInfo[j].point ).LengthSqr() < Square( 2.0f ) ) {
   5659 							break;
   5660 						}
   5661 						if ( idMath::Fabs( contacts[k].normal * contactInfo[j].normal ) > 0.9f ) {
   5662 							numBodyContacts++;
   5663 						}
   5664 					}
   5665 				}
   5666 			}
   5667 
   5668 			if ( k >= contacts.Num() && numBodyContacts < 3 ) {
   5669 				contacts.Append( contactInfo[j] );
   5670 				contactBodies.Append( i );
   5671 			}
   5672 		}
   5673 
   5674 #else
   5675 
   5676 		for ( j = 0; j < numContacts; j++ ) {
   5677 			contacts.Append( contactInfo[j] );
   5678 			contactBodies.Append( i );
   5679 		}
   5680 #endif
   5681 
   5682 	}
   5683 
   5684 	AddContactEntitiesForContacts();
   5685 
   5686 	return ( contacts.Num() != 0 );
   5687 }
   5688 
   5689 /*
   5690 ================
   5691 idPhysics_AF::SetupContactConstraints
   5692 ================
   5693 */
   5694 void idPhysics_AF::SetupContactConstraints() {
   5695 	int i;
   5696 
   5697 	// make sure enough contact constraints are allocated
   5698 	contactConstraints.AssureSizeAlloc( contacts.Num(), idListNewElement<idAFConstraint_Contact> );
   5699 	contactConstraints.SetNum( contacts.Num() );
   5700 
   5701 	// setup contact constraints
   5702 	for ( i = 0; i < contacts.Num(); i++ ) {
   5703 		// add contact constraint
   5704 		contactConstraints[i]->physics = this;
   5705 		if ( contacts[i].entityNum == self->entityNumber ) {
   5706 			contactConstraints[i]->Setup( bodies[contactBodies[i]], bodies[ contacts[i].id ], contacts[i] );
   5707 		}
   5708 		else {
   5709 			contactConstraints[i]->Setup( bodies[contactBodies[i]], NULL, contacts[i] );
   5710 		}
   5711 	}
   5712 }
   5713 
   5714 /*
   5715 ================
   5716 idPhysics_AF::ApplyContactForces
   5717 ================
   5718 */
   5719 void idPhysics_AF::ApplyContactForces() {
   5720 #if 0
   5721 	int i;
   5722 	idEntity *ent;
   5723 	idVec3 force;
   5724 
   5725 	for ( i = 0; i < contactConstraints.Num(); i++ ) {
   5726 		if ( contactConstraints[i]->body2 != NULL ) {
   5727 			continue;
   5728 		}
   5729 		const contactInfo_t &contact = contactConstraints[i]->GetContact();
   5730 		ent = gameLocal.entities[contact.entityNum];
   5731 		if ( !ent ) {
   5732 			continue;
   5733 		}
   5734 		force.Zero();
   5735 		ent->AddForce( self, contact.id, contact.point, force );
   5736 	}
   5737 #endif
   5738 }
   5739 
   5740 /*
   5741 ================
   5742 idPhysics_AF::ClearExternalForce
   5743 ================
   5744 */
   5745 void idPhysics_AF::ClearExternalForce() {
   5746 	int i;
   5747 	idAFBody *body;
   5748 
   5749 	for ( i = 0; i < bodies.Num(); i++ ) {
   5750 		body = bodies[i];
   5751 
   5752 		// clear external force
   5753 		body->current->externalForce.Zero();
   5754 		body->next->externalForce.Zero();
   5755 	}
   5756 }
   5757 
   5758 /*
   5759 ================
   5760 idPhysics_AF::AddGravity
   5761 ================
   5762 */
   5763 void idPhysics_AF::AddGravity() {
   5764 	int i;
   5765 	idAFBody *body;
   5766 
   5767 	for ( i = 0; i < bodies.Num(); i++ ) {
   5768 		body = bodies[i];
   5769 		// add gravitational force
   5770 		body->current->externalForce.SubVec3( 0 ) += body->mass * gravityVector;
   5771 	}
   5772 }
   5773 
   5774 /*
   5775 ================
   5776 idPhysics_AF::SwapStates
   5777 ================
   5778 */
   5779 void idPhysics_AF::SwapStates() {
   5780 	int i;
   5781 	idAFBody *body;
   5782 	AFBodyPState_t *swap;
   5783 
   5784 	for ( i = 0; i < bodies.Num(); i++ ) {
   5785 
   5786 		body = bodies[i];
   5787 
   5788 		// swap the current and next state for next simulation step
   5789 		swap = body->current;
   5790 		body->current = body->next;
   5791 		body->next = swap;
   5792 	}
   5793 }
   5794 
   5795 /*
   5796 ================
   5797 idPhysics_AF::UpdateClipModels
   5798 ================
   5799 */
   5800 void idPhysics_AF::UpdateClipModels() {
   5801 	int i;
   5802 	idAFBody *body;
   5803 
   5804 	for ( i = 0; i < bodies.Num(); i++ ) {
   5805 		body = bodies[i];
   5806 		body->clipModel->Link( gameLocal.clip, self, body->clipModel->GetId(), body->current->worldOrigin, body->current->worldAxis );
   5807 	}
   5808 }
   5809 
   5810 /*
   5811 ================
   5812 idPhysics_AF::SetSuspendSpeed
   5813 ================
   5814 */
   5815 void idPhysics_AF::SetSuspendSpeed( const idVec2 &velocity, const idVec2 &acceleration ) {
   5816 	this->suspendVelocity = velocity;
   5817 	this->suspendAcceleration = acceleration;
   5818 }
   5819 
   5820 /*
   5821 ================
   5822 idPhysics_AF::SetSuspendTime
   5823 ================
   5824 */
   5825 void idPhysics_AF::SetSuspendTime( const float minTime, const float maxTime ) {
   5826 	this->minMoveTime = minTime;
   5827 	this->maxMoveTime = maxTime;
   5828 }
   5829 
   5830 /*
   5831 ================
   5832 idPhysics_AF::SetSuspendTolerance
   5833 ================
   5834 */
   5835 void idPhysics_AF::SetSuspendTolerance( const float noMoveTime, const float noMoveTranslation, const float noMoveRotation ) {
   5836 	this->noMoveTime = noMoveTime;
   5837 	this->noMoveTranslation = noMoveTranslation;
   5838 	this->noMoveRotation = noMoveRotation;
   5839 }
   5840 
   5841 /*
   5842 ================
   5843 idPhysics_AF::SetTimeScaleRamp
   5844 ================
   5845 */
   5846 void idPhysics_AF::SetTimeScaleRamp( const float start, const float end ) {
   5847 	timeScaleRampStart = start;
   5848 	timeScaleRampEnd = end;
   5849 }
   5850 
   5851 /*
   5852 ================
   5853 idPhysics_AF::SetJointFrictionDent
   5854 ================
   5855 */
   5856 void idPhysics_AF::SetJointFrictionDent( const float dent, const float start, const float end ) {
   5857 	jointFrictionDent = dent;
   5858 	jointFrictionDentStart = start;
   5859 	jointFrictionDentEnd = end;
   5860 }
   5861 
   5862 /*
   5863 ================
   5864 idPhysics_AF::GetJointFrictionScale
   5865 ================
   5866 */
   5867 float idPhysics_AF::GetJointFrictionScale() const {
   5868 	if ( jointFrictionDentScale > 0.0f ) {
   5869 		return jointFrictionDentScale;
   5870 	} else if ( jointFrictionScale > 0.0f ) {
   5871 		return jointFrictionScale;
   5872 	} else if ( af_jointFrictionScale.GetFloat() > 0.0f ) {
   5873 		return af_jointFrictionScale.GetFloat();
   5874 	}
   5875 	return 1.0f;
   5876 }
   5877 
   5878 /*
   5879 ================
   5880 idPhysics_AF::SetContactFrictionDent
   5881 ================
   5882 */
   5883 void idPhysics_AF::SetContactFrictionDent( const float dent, const float start, const float end ) {
   5884 	contactFrictionDent = dent;
   5885 	contactFrictionDentStart = start;
   5886 	contactFrictionDentEnd = end;
   5887 }
   5888 
   5889 /*
   5890 ================
   5891 idPhysics_AF::GetContactFrictionScale
   5892 ================
   5893 */
   5894 float idPhysics_AF::GetContactFrictionScale() const {
   5895 	if ( contactFrictionDentScale > 0.0f ) {
   5896 		return contactFrictionDentScale;
   5897 	} else if ( contactFrictionScale > 0.0f ) {
   5898 		return contactFrictionScale;
   5899 	} else if ( af_contactFrictionScale.GetFloat() > 0.0f ) {
   5900 		return af_contactFrictionScale.GetFloat();
   5901 	}
   5902 	return 1.0f;
   5903 }
   5904 
   5905 /*
   5906 ================
   5907 idPhysics_AF::TestIfAtRest
   5908 ================
   5909 */
   5910 bool idPhysics_AF::TestIfAtRest( float timeStep ) {
   5911 	int i;
   5912 	float translationSqr, maxTranslationSqr, rotation, maxRotation;
   5913 	idAFBody *body;
   5914 
   5915 	if ( current.atRest >= 0 ) {
   5916 		return true;
   5917 	}
   5918 
   5919 	current.activateTime += timeStep;
   5920 
   5921 	// if the simulation should never be suspended before a certaint amount of time passed
   5922 	if ( minMoveTime > 0.0f && current.activateTime < minMoveTime ) {
   5923 		return false;
   5924 	}
   5925 
   5926 	// if the simulation should always be suspended after a certain amount time passed
   5927 	if ( maxMoveTime > 0.0f && current.activateTime > maxMoveTime ) {
   5928 		return true;
   5929 	}
   5930 
   5931 	// test if all bodies hardly moved over a period of time
   5932 	if ( current.noMoveTime == 0.0f ) {
   5933 		for ( i = 0; i < bodies.Num(); i++ ) {
   5934 			body = bodies[i];
   5935 			body->atRestOrigin = body->current->worldOrigin;
   5936 			body->atRestAxis = body->current->worldAxis;
   5937 		}
   5938 		current.noMoveTime += timeStep;
   5939 	}
   5940 	else if ( current.noMoveTime > noMoveTime ) {
   5941 		current.noMoveTime = 0.0f;
   5942 		maxTranslationSqr = 0.0f;
   5943 		maxRotation = 0.0f;
   5944 		for ( i = 0; i < bodies.Num(); i++ ) {
   5945 			body = bodies[i];
   5946 
   5947 			translationSqr = ( body->current->worldOrigin - body->atRestOrigin ).LengthSqr();
   5948 			if ( translationSqr > maxTranslationSqr ) {
   5949 				maxTranslationSqr = translationSqr;
   5950 			}
   5951 			rotation = ( body->atRestAxis.Transpose() * body->current->worldAxis ).ToRotation().GetAngle();
   5952 			if ( rotation > maxRotation ) {
   5953 				maxRotation = rotation;
   5954 			}
   5955 		}
   5956 
   5957 		if ( maxTranslationSqr < Square( noMoveTranslation ) && maxRotation < noMoveRotation ) {
   5958 			// hardly moved over a period of time so the articulated figure may come to rest
   5959 			return true;
   5960 		}
   5961 	} else {
   5962 		current.noMoveTime += timeStep;
   5963 	}
   5964 
   5965 	// test if the velocity or acceleration of any body is still too large to come to rest
   5966 	for ( i = 0; i < bodies.Num(); i++ ) {
   5967 		body = bodies[i];
   5968 
   5969 		if ( body->current->spatialVelocity.SubVec3(0).LengthSqr() > Square( suspendVelocity[0] ) ) {
   5970 			return false;
   5971 		}
   5972 		if ( body->current->spatialVelocity.SubVec3(1).LengthSqr() > Square( suspendVelocity[1] ) ) {
   5973 			return false;
   5974 		}
   5975 		if ( body->acceleration.SubVec3(0).LengthSqr() > Square( suspendAcceleration[0] ) ) {
   5976 			return false;
   5977 		}
   5978 		if ( body->acceleration.SubVec3(1).LengthSqr() > Square( suspendAcceleration[1] ) ) {
   5979 			return false;
   5980 		}
   5981 	}
   5982 
   5983 	// all bodies have a velocity and acceleration small enough to come to rest
   5984 	return true;
   5985 }
   5986 
   5987 /*
   5988 ================
   5989 idPhysics_AF::Rest
   5990 ================
   5991 */
   5992 void idPhysics_AF::Rest() {
   5993 	int i;
   5994 
   5995 	current.atRest = gameLocal.time;
   5996 
   5997 	for ( i = 0; i < bodies.Num(); i++ ) {
   5998 		bodies[i]->current->spatialVelocity.Zero();
   5999 		bodies[i]->current->externalForce.Zero();
   6000 	}
   6001 
   6002 	self->BecomeInactive( TH_PHYSICS );
   6003 }
   6004 
   6005 /*
   6006 ================
   6007 idPhysics_AF::Activate
   6008 ================
   6009 */
   6010 void idPhysics_AF::Activate() {
   6011 	// if the articulated figure was at rest
   6012 	if ( current.atRest >= 0 ) {
   6013 		// normally gravity is added at the end of a simulation frame
   6014 		// if the figure was at rest add gravity here so it is applied this simulation frame
   6015 		AddGravity();
   6016 		// reset the active time for the max move time
   6017 		current.activateTime = 0.0f;
   6018 	}
   6019 	current.atRest = -1;
   6020 	current.noMoveTime = 0.0f;
   6021 	self->BecomeActive( TH_PHYSICS );
   6022 }
   6023 
   6024 /*
   6025 ================
   6026 idPhysics_AF::PutToRest
   6027 
   6028   put to rest untill something collides with this physics object
   6029 ================
   6030 */
   6031 void idPhysics_AF::PutToRest() {
   6032 	Rest();
   6033 }
   6034 
   6035 /*
   6036 ================
   6037 idPhysics_AF::EnableImpact
   6038 ================
   6039 */
   6040 void idPhysics_AF::EnableImpact() {
   6041 	noImpact = false;
   6042 }
   6043 
   6044 /*
   6045 ================
   6046 idPhysics_AF::DisableImpact
   6047 ================
   6048 */
   6049 void idPhysics_AF::DisableImpact() {
   6050 	noImpact = true;
   6051 }
   6052 
   6053 /*
   6054 ================
   6055 idPhysics_AF::AddPushVelocity
   6056 ================
   6057 */
   6058 void idPhysics_AF::AddPushVelocity( const idVec6 &pushVelocity ) {
   6059 	int i;
   6060 
   6061 	if ( pushVelocity != vec6_origin ) {
   6062 		for ( i = 0; i < bodies.Num(); i++ ) {
   6063 			bodies[i]->current->spatialVelocity += pushVelocity;
   6064 		}
   6065 	}
   6066 }
   6067 
   6068 /*
   6069 ================
   6070 idPhysics_AF::SetClipModel
   6071 ================
   6072 */
   6073 void idPhysics_AF::SetClipModel( idClipModel *model, float density, int id, bool freeOld ) {
   6074 }
   6075 
   6076 /*
   6077 ================
   6078 idPhysics_AF::GetClipModel
   6079 ================
   6080 */
   6081 idClipModel *idPhysics_AF::GetClipModel( int id ) const {
   6082 	if ( id >= 0 && id < bodies.Num() ) {
   6083 		return bodies[id]->GetClipModel();
   6084 	}
   6085 	return NULL;
   6086 }
   6087 
   6088 /*
   6089 ================
   6090 idPhysics_AF::GetNumClipModels
   6091 ================
   6092 */
   6093 int idPhysics_AF::GetNumClipModels() const {
   6094 	return bodies.Num();
   6095 }
   6096 
   6097 /*
   6098 ================
   6099 idPhysics_AF::SetMass
   6100 ================
   6101 */
   6102 void idPhysics_AF::SetMass( float mass, int id ) {
   6103 	if ( id >= 0 && id < bodies.Num() ) {
   6104 	}
   6105 	else {
   6106 		forceTotalMass = mass;
   6107 	}
   6108 	SetChanged();
   6109 }
   6110 
   6111 /*
   6112 ================
   6113 idPhysics_AF::GetMass
   6114 ================
   6115 */
   6116 float idPhysics_AF::GetMass( int id ) const {
   6117 	if ( id >= 0 && id < bodies.Num() ) {
   6118 		return bodies[id]->mass;
   6119 	}
   6120 	return totalMass;
   6121 }
   6122 
   6123 /*
   6124 ================
   6125 idPhysics_AF::SetContents
   6126 ================
   6127 */
   6128 void idPhysics_AF::SetContents( int contents, int id ) {
   6129 	int i;
   6130 
   6131 	if ( id >= 0 && id < bodies.Num() ) {
   6132 		bodies[id]->GetClipModel()->SetContents( contents );
   6133 	}
   6134 	else {
   6135 		for ( i = 0; i < bodies.Num(); i++ ) {
   6136 			bodies[i]->GetClipModel()->SetContents( contents );
   6137 		}
   6138 	}
   6139 }
   6140 
   6141 /*
   6142 ================
   6143 idPhysics_AF::GetContents
   6144 ================
   6145 */
   6146 int idPhysics_AF::GetContents( int id ) const {
   6147 	int i, contents;
   6148 
   6149 	if ( id >= 0 && id < bodies.Num() ) {
   6150 		return bodies[id]->GetClipModel()->GetContents();
   6151 	}
   6152 	else {
   6153 		contents = 0;
   6154 		for ( i = 0; i < bodies.Num(); i++ ) {
   6155 			contents |= bodies[i]->GetClipModel()->GetContents();
   6156 		}
   6157 		return contents;
   6158 	}
   6159 }
   6160 
   6161 /*
   6162 ================
   6163 idPhysics_AF::GetBounds
   6164 ================
   6165 */
   6166 const idBounds &idPhysics_AF::GetBounds( int id ) const {
   6167 	int i;
   6168 	static idBounds relBounds;
   6169 
   6170 	if ( id >= 0 && id < bodies.Num() ) {
   6171 		return bodies[id]->GetClipModel()->GetBounds();
   6172 	}
   6173 	else if ( !bodies.Num() ) {
   6174 		relBounds.Zero();
   6175 		return relBounds;
   6176 	}
   6177 	else {
   6178 		relBounds = bodies[0]->GetClipModel()->GetBounds();
   6179 		for ( i = 1; i < bodies.Num(); i++ ) {
   6180 			idBounds bounds;
   6181 			idVec3 origin = ( bodies[i]->GetWorldOrigin() - bodies[0]->GetWorldOrigin() ) * bodies[0]->GetWorldAxis().Transpose();
   6182 			idMat3 axis = bodies[i]->GetWorldAxis() * bodies[0]->GetWorldAxis().Transpose();
   6183 			bounds.FromTransformedBounds( bodies[i]->GetClipModel()->GetBounds(), origin, axis );
   6184 			relBounds += bounds;
   6185 		}
   6186 		return relBounds;
   6187 	}
   6188 }
   6189 
   6190 /*
   6191 ================
   6192 idPhysics_AF::GetAbsBounds
   6193 ================
   6194 */
   6195 const idBounds &idPhysics_AF::GetAbsBounds( int id ) const {
   6196 	int i;
   6197 	static idBounds absBounds;
   6198 
   6199 	if ( id >= 0 && id < bodies.Num() ) {
   6200 		return bodies[id]->GetClipModel()->GetAbsBounds();
   6201 	}
   6202 	else if ( !bodies.Num() ) {
   6203 		absBounds.Zero();
   6204 		return absBounds;
   6205 	}
   6206 	else {
   6207 		absBounds = bodies[0]->GetClipModel()->GetAbsBounds();
   6208 		for ( i = 1; i < bodies.Num(); i++ ) {
   6209 			absBounds += bodies[i]->GetClipModel()->GetAbsBounds();
   6210 		}
   6211 		return absBounds;
   6212 	}
   6213 }
   6214 
   6215 /*
   6216 ================
   6217 idPhysics_AF::Evaluate
   6218 ================
   6219 */
   6220 bool idPhysics_AF::Evaluate( int timeStepMSec, int endTimeMSec ) {
   6221 	float timeStep;
   6222 
   6223 	if ( timeScaleRampStart < MS2SEC( endTimeMSec ) && timeScaleRampEnd > MS2SEC( endTimeMSec ) ) {
   6224 		timeStep = MS2SEC( timeStepMSec ) * ( MS2SEC( endTimeMSec ) - timeScaleRampStart ) / ( timeScaleRampEnd - timeScaleRampStart );
   6225 	} else if ( af_timeScale.GetFloat() != 1.0f ) {
   6226 		timeStep = MS2SEC( timeStepMSec ) * af_timeScale.GetFloat();
   6227 	} else {
   6228 		timeStep = MS2SEC( timeStepMSec ) * timeScale;
   6229 	}
   6230 	current.lastTimeStep = timeStep;
   6231 
   6232 
   6233 	// if the articulated figure changed
   6234 	if ( changedAF || ( linearTime != af_useLinearTime.GetBool() ) ) {
   6235 		BuildTrees();
   6236 		changedAF = false;
   6237 		linearTime = af_useLinearTime.GetBool();
   6238 	}
   6239 
   6240 	// get the new master position
   6241 	if ( masterBody ) {
   6242 		idVec3 masterOrigin;
   6243 		idMat3 masterAxis;
   6244 		self->GetMasterPosition( masterOrigin, masterAxis );
   6245 		if ( current.atRest >= 0 && ( masterBody->current->worldOrigin != masterOrigin || masterBody->current->worldAxis != masterAxis ) ) {
   6246 			Activate();
   6247 		}
   6248 		masterBody->current->worldOrigin = masterOrigin;
   6249 		masterBody->current->worldAxis = masterAxis;
   6250 	}
   6251 
   6252 	// if the simulation is suspended because the figure is at rest
   6253 	if ( current.atRest >= 0 || timeStep <= 0.0f ) {
   6254 		DebugDraw();
   6255 		return false;
   6256 	}
   6257 
   6258 	// move the af velocity into the frame of a pusher
   6259 	AddPushVelocity( -current.pushVelocity );
   6260 
   6261 #ifdef AF_TIMINGS
   6262 	timer_total.Start();
   6263 #endif
   6264 
   6265 #ifdef AF_TIMINGS
   6266 	timer_collision.Start();
   6267 #endif
   6268 
   6269 	// evaluate contacts
   6270 	EvaluateContacts();
   6271 
   6272 	// setup contact constraints
   6273 	SetupContactConstraints();
   6274 
   6275 #ifdef AF_TIMINGS
   6276 	timer_collision.Stop();
   6277 #endif
   6278 
   6279 	// evaluate constraint equations
   6280 	EvaluateConstraints( timeStep );
   6281 
   6282 	// apply friction
   6283 	ApplyFriction( timeStep, endTimeMSec );
   6284 
   6285 	// add frame constraints
   6286 	AddFrameConstraints();
   6287 
   6288 #ifdef AF_TIMINGS
   6289 	int i, numPrimary = 0, numAuxiliary = 0;
   6290 	for ( i = 0; i < primaryConstraints.Num(); i++ ) {
   6291 		numPrimary += primaryConstraints[i]->J1.GetNumRows();
   6292 	}
   6293 	for ( i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   6294 		numAuxiliary += auxiliaryConstraints[i]->J1.GetNumRows();
   6295 	}
   6296 	timer_pc.Start();
   6297 #endif
   6298 
   6299 	// factor matrices for primary constraints
   6300 	PrimaryFactor();
   6301 
   6302 	// calculate forces on bodies after applying primary constraints
   6303 	PrimaryForces( timeStep );
   6304 
   6305 #ifdef AF_TIMINGS
   6306 	timer_pc.Stop();
   6307 	timer_ac.Start();
   6308 #endif
   6309 
   6310 	// calculate and apply auxiliary constraint forces
   6311 	AuxiliaryForces( timeStep );
   6312 
   6313 #ifdef AF_TIMINGS
   6314 	timer_ac.Stop();
   6315 #endif
   6316 
   6317 	// evolve current state to next state
   6318 	Evolve( timeStep );
   6319 
   6320 	// debug graphics
   6321 	DebugDraw();
   6322 
   6323 	// clear external forces on all bodies
   6324 	ClearExternalForce();
   6325 
   6326 	// apply contact force to other entities
   6327 	ApplyContactForces();
   6328 
   6329 	// remove all frame constraints
   6330 	RemoveFrameConstraints();
   6331 
   6332 #ifdef AF_TIMINGS
   6333 	timer_collision.Start();
   6334 #endif
   6335 
   6336 	// check for collisions between current and next state
   6337 	CheckForCollisions( timeStep );
   6338 
   6339 #ifdef AF_TIMINGS
   6340 	timer_collision.Stop();
   6341 #endif
   6342 
   6343 	// swap the current and next state
   6344 	SwapStates();
   6345 
   6346 	// make sure all clip models are disabled in case they were enabled for self collision
   6347 	if ( selfCollision && !af_skipSelfCollision.GetBool() ) {
   6348 		DisableClip();
   6349 	}
   6350 
   6351 	// apply collision impulses
   6352 	if ( ApplyCollisions( timeStep ) ) {
   6353 		current.atRest = gameLocal.time;
   6354 		comeToRest = true;
   6355 	}
   6356 
   6357 	// test if the simulation can be suspended because the whole figure is at rest
   6358 	if ( comeToRest && TestIfAtRest( timeStep ) ) {
   6359 		Rest();
   6360 	} else {
   6361 		ActivateContactEntities();
   6362 	}
   6363 
   6364 	// add gravitational force
   6365 	AddGravity();
   6366 
   6367 	// move the af velocity back into the world frame
   6368 	AddPushVelocity( current.pushVelocity );
   6369 	current.pushVelocity.Zero();
   6370 
   6371 	if ( IsOutsideWorld() ) {
   6372 		gameLocal.Warning( "articulated figure moved outside world bounds for entity '%s' type '%s' at (%s)",
   6373 							self->name.c_str(), self->GetType()->classname, bodies[0]->current->worldOrigin.ToString(0) );
   6374 		Rest();
   6375 	}
   6376 
   6377 #ifdef AF_TIMINGS
   6378 	timer_total.Stop();
   6379 
   6380 	if ( af_showTimings.GetInteger() == 1 ) {
   6381 		gameLocal.Printf( "%12s: t %1.4f pc %2d, %1.4f ac %2d %1.4f lcp %1.4f cd %1.4f\n",
   6382 						self->name.c_str(),
   6383 						timer_total.Milliseconds(),
   6384 						numPrimary, timer_pc.Milliseconds(),
   6385 						numAuxiliary, timer_ac.Milliseconds() - timer_lcp.Milliseconds(),
   6386 						timer_lcp.Milliseconds(), timer_collision.Milliseconds() );
   6387 	}
   6388 	else if ( af_showTimings.GetInteger() == 2 ) {
   6389 		numArticulatedFigures++;
   6390 		if ( endTimeMSec > lastTimerReset ) {
   6391 			gameLocal.Printf( "af %d: t %1.4f pc %2d, %1.4f ac %2d %1.4f lcp %1.4f cd %1.4f\n",
   6392 							numArticulatedFigures,
   6393 							timer_total.Milliseconds(),
   6394 							numPrimary, timer_pc.Milliseconds(),
   6395 							numAuxiliary, timer_ac.Milliseconds() - timer_lcp.Milliseconds(),
   6396 							timer_lcp.Milliseconds(), timer_collision.Milliseconds() );
   6397 		}
   6398 	}
   6399 
   6400 	if ( endTimeMSec > lastTimerReset ) {
   6401 		lastTimerReset = endTimeMSec;
   6402 		numArticulatedFigures = 0;
   6403 		timer_total.Clear();
   6404 		timer_pc.Clear();
   6405 		timer_ac.Clear();
   6406 		timer_collision.Clear();
   6407 		timer_lcp.Clear();
   6408 	}
   6409 #endif
   6410 
   6411 	return true;
   6412 }
   6413 
   6414 /*
   6415 ================
   6416 idPhysics_AF::UpdateTime
   6417 ================
   6418 */
   6419 void idPhysics_AF::UpdateTime( int endTimeMSec ) {
   6420 }
   6421 
   6422 /*
   6423 ================
   6424 idPhysics_AF::GetTime
   6425 ================
   6426 */
   6427 int idPhysics_AF::GetTime() const {
   6428 	return gameLocal.time;
   6429 }
   6430 
   6431 /*
   6432 ================
   6433 DrawTraceModelSilhouette
   6434 ================
   6435 */
   6436 void DrawTraceModelSilhouette( const idVec3 &projectionOrigin, const idClipModel *clipModel ) {
   6437 	int i, numSilEdges;
   6438 	int silEdges[MAX_TRACEMODEL_EDGES];
   6439 	idVec3 v1, v2;
   6440 	const idTraceModel *trm = clipModel->GetTraceModel();
   6441 	const idVec3 &origin = clipModel->GetOrigin();
   6442 	const idMat3 &axis = clipModel->GetAxis();
   6443 
   6444 	numSilEdges = trm->GetProjectionSilhouetteEdges( ( projectionOrigin - origin ) * axis.Transpose(), silEdges );
   6445 	for ( i = 0; i < numSilEdges; i++ ) {
   6446 		v1 = trm->verts[ trm->edges[ abs(silEdges[i]) ].v[ INT32_SIGNBITSET( silEdges[i] ) ] ];
   6447 		v2 = trm->verts[ trm->edges[ abs(silEdges[i]) ].v[ INT32_SIGNBITNOTSET( silEdges[i] ) ] ];
   6448 		gameRenderWorld->DebugArrow( colorRed, origin + v1 * axis, origin + v2 * axis, 1 );
   6449 	}
   6450 }
   6451 
   6452 /*
   6453 ================
   6454 idPhysics_AF::DebugDraw
   6455 ================
   6456 */
   6457 void idPhysics_AF::DebugDraw() {
   6458 	int i;
   6459 	idAFBody *body, *highlightBody = NULL, *constrainedBody1 = NULL, *constrainedBody2 = NULL;
   6460 	idAFConstraint *constraint;
   6461 	idVec3 center;
   6462 	idMat3 axis;
   6463 
   6464 	if ( af_highlightConstraint.GetString()[0] ) {
   6465 		constraint = GetConstraint( af_highlightConstraint.GetString() );
   6466 		if ( constraint ) {
   6467 			constraint->GetCenter( center );
   6468 			axis = gameLocal.GetLocalPlayer()->viewAngles.ToMat3();
   6469 			gameRenderWorld->DebugCone( colorYellow, center, (axis[2] - axis[1]) * 4.0f, 0.0f, 1.0f, 0 );
   6470 
   6471 			if ( af_showConstrainedBodies.GetBool() ) {
   6472 				cvarSystem->SetCVarString( "cm_drawColor", colorCyan.ToString( 0 ) );
   6473 				constrainedBody1 = constraint->body1;
   6474 				if ( constrainedBody1 ) {
   6475 					collisionModelManager->DrawModel( constrainedBody1->clipModel->Handle(), constrainedBody1->clipModel->GetOrigin(),
   6476 											constrainedBody1->clipModel->GetAxis(), vec3_origin, 0.0f );
   6477 				}
   6478 				cvarSystem->SetCVarString( "cm_drawColor", colorBlue.ToString( 0 ) );
   6479 				constrainedBody2 = constraint->body2;
   6480 				if ( constrainedBody2 ) {
   6481 					collisionModelManager->DrawModel( constrainedBody2->clipModel->Handle(), constrainedBody2->clipModel->GetOrigin(),
   6482 											constrainedBody2->clipModel->GetAxis(), vec3_origin, 0.0f );
   6483 				}
   6484 				cvarSystem->SetCVarString( "cm_drawColor", colorRed.ToString( 0 ) );
   6485 			}
   6486 		}
   6487 	}
   6488 
   6489 	if ( af_highlightBody.GetString()[0] ) {
   6490 		highlightBody = GetBody( af_highlightBody.GetString() );
   6491 		if ( highlightBody ) {
   6492 			cvarSystem->SetCVarString( "cm_drawColor", colorYellow.ToString( 0 ) );
   6493 			collisionModelManager->DrawModel( highlightBody->clipModel->Handle(), highlightBody->clipModel->GetOrigin(),
   6494 									highlightBody->clipModel->GetAxis(), vec3_origin, 0.0f );
   6495 			cvarSystem->SetCVarString( "cm_drawColor", colorRed.ToString( 0 ) );
   6496 		}
   6497 	}
   6498 
   6499 	if ( af_showBodies.GetBool() ) {
   6500 		for ( i = 0; i < bodies.Num(); i++ ) {
   6501 			body = bodies[i];
   6502 			if ( body == constrainedBody1 || body == constrainedBody2 ) {
   6503 				continue;
   6504 			}
   6505 			if ( body == highlightBody ) {
   6506 				continue;
   6507 			}
   6508 			collisionModelManager->DrawModel( body->clipModel->Handle(), body->clipModel->GetOrigin(),
   6509 										body->clipModel->GetAxis(), vec3_origin, 0.0f );
   6510 			//DrawTraceModelSilhouette( gameLocal.GetLocalPlayer()->GetEyePosition(), body->clipModel );
   6511 		}
   6512 	}
   6513 
   6514 	if ( af_showBodyNames.GetBool() ) {
   6515 		for ( i = 0; i < bodies.Num(); i++ ) {
   6516 			body = bodies[i];
   6517 			gameRenderWorld->DrawText( body->GetName().c_str(), body->GetWorldOrigin(), 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
   6518 		}
   6519 	}
   6520 
   6521 	if ( af_showMass.GetBool() ) {
   6522 		for ( i = 0; i < bodies.Num(); i++ ) {
   6523 			body = bodies[i];
   6524 			gameRenderWorld->DrawText( va( "\n%1.2f", 1.0f / body->GetInverseMass() ), body->GetWorldOrigin(), 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
   6525 		}
   6526 	}
   6527 
   6528 	if ( af_showTotalMass.GetBool() ) {
   6529 		axis = gameLocal.GetLocalPlayer()->viewAngles.ToMat3();
   6530 		gameRenderWorld->DrawText( va( "\n%1.2f", totalMass ), bodies[0]->GetWorldOrigin() + axis[2] * 8.0f, 0.15f, colorCyan, axis, 1 );
   6531 	}
   6532 
   6533 	if ( af_showInertia.GetBool() ) {
   6534 		for ( i = 0; i < bodies.Num(); i++ ) {
   6535 			body = bodies[i];
   6536 			idMat3 &I = body->inertiaTensor;
   6537 			gameRenderWorld->DrawText( va( "\n\n\n( %.1f %.1f %.1f )\n( %.1f %.1f %.1f )\n( %.1f %.1f %.1f )",
   6538 										I[0].x, I[0].y, I[0].z,
   6539 										I[1].x, I[1].y, I[1].z,
   6540 										I[2].x, I[2].y, I[2].z ),
   6541 										body->GetWorldOrigin(), 0.05f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
   6542 		}
   6543 	}
   6544 
   6545 	if ( af_showVelocity.GetBool() ) {
   6546 		for ( i = 0; i < bodies.Num(); i++ ) {
   6547 			DrawVelocity( bodies[i]->clipModel->GetId(), 0.1f, 4.0f );
   6548 		}
   6549 	}
   6550 
   6551 	if ( af_showConstraints.GetBool() ) {
   6552 		for ( i = 0; i < primaryConstraints.Num(); i++ ) {
   6553 			constraint = primaryConstraints[i];
   6554 			constraint->DebugDraw();
   6555 		}
   6556 		if ( !af_showPrimaryOnly.GetBool() ) {
   6557 			for ( i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   6558 				constraint = auxiliaryConstraints[i];
   6559 				constraint->DebugDraw();
   6560 			}
   6561 		}
   6562 	}
   6563 
   6564 	if ( af_showConstraintNames.GetBool() ) {
   6565 		for ( i = 0; i < primaryConstraints.Num(); i++ ) {
   6566 			constraint = primaryConstraints[i];
   6567 			constraint->GetCenter( center );
   6568 			gameRenderWorld->DrawText( constraint->GetName().c_str(), center, 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
   6569 		}
   6570 		if ( !af_showPrimaryOnly.GetBool() ) {
   6571 			for ( i = 0; i < auxiliaryConstraints.Num(); i++ ) {
   6572 				constraint = auxiliaryConstraints[i];
   6573 				constraint->GetCenter( center );
   6574 				gameRenderWorld->DrawText( constraint->GetName().c_str(), center, 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
   6575 			}
   6576 		}
   6577 	}
   6578 
   6579 	if ( af_showTrees.GetBool() || ( af_showActive.GetBool() && current.atRest < 0 ) ) {
   6580 		for ( i = 0; i < trees.Num(); i++ ) {
   6581 			trees[i]->DebugDraw( idStr::ColorForIndex( i+3 ) );
   6582 		}
   6583 	}
   6584 }
   6585 
   6586 /*
   6587 ================
   6588 idPhysics_AF::idPhysics_AF
   6589 ================
   6590 */
   6591 idPhysics_AF::idPhysics_AF() {
   6592 	trees.Clear();
   6593 	bodies.Clear();
   6594 	constraints.Clear();
   6595 	primaryConstraints.Clear();
   6596 	auxiliaryConstraints.Clear();
   6597 	frameConstraints.Clear();
   6598 	contacts.Clear();
   6599 	collisions.Clear();
   6600 	changedAF = true;
   6601 	masterBody = NULL;
   6602 
   6603 	lcp = idLCP::AllocSymmetric();
   6604 
   6605 	memset( &current, 0, sizeof( current ) );
   6606 	current.atRest = -1;
   6607 	current.lastTimeStep = 0.0f;
   6608 	saved = current;
   6609 
   6610 	linearFriction = 0.005f;
   6611 	angularFriction = 0.005f;
   6612 	contactFriction = 0.8f;
   6613 	bouncyness = 0.4f;
   6614 	totalMass = 0.0f;
   6615 	forceTotalMass = -1.0f;
   6616 
   6617 	suspendVelocity.Set( SUSPEND_LINEAR_VELOCITY, SUSPEND_ANGULAR_VELOCITY );
   6618 	suspendAcceleration.Set( SUSPEND_LINEAR_ACCELERATION, SUSPEND_LINEAR_ACCELERATION );
   6619 	noMoveTime = NO_MOVE_TIME;
   6620 	noMoveTranslation = NO_MOVE_TRANSLATION_TOLERANCE;
   6621 	noMoveRotation = NO_MOVE_ROTATION_TOLERANCE;
   6622 	minMoveTime = MIN_MOVE_TIME;
   6623 	maxMoveTime = MAX_MOVE_TIME;
   6624 	impulseThreshold = IMPULSE_THRESHOLD;
   6625 
   6626 	timeScale = 1.0f;
   6627 	timeScaleRampStart = 0.0f;
   6628 	timeScaleRampEnd = 0.0f;
   6629 
   6630 	jointFrictionScale = 0.0f;
   6631 	jointFrictionDent = 0.0f;
   6632 	jointFrictionDentStart = 0.0f;
   6633 	jointFrictionDentEnd = 0.0f;
   6634 	jointFrictionDentScale = 0.0f;
   6635 
   6636 	contactFrictionScale = 0.0f;
   6637 	contactFrictionDent = 0.0f;
   6638 	contactFrictionDentStart = 0.0f;
   6639 	contactFrictionDentEnd = 0.0f;
   6640 	contactFrictionDentScale = 0.0f;
   6641 
   6642 	enableCollision = true;
   6643 	selfCollision = true;
   6644 	comeToRest = true;
   6645 	linearTime = true;
   6646 	noImpact = false;
   6647 	worldConstraintsLocked = false;
   6648 	forcePushable = false;
   6649 
   6650 #ifdef AF_TIMINGS
   6651 	lastTimerReset = 0;
   6652 #endif
   6653 }
   6654 
   6655 /*
   6656 ================
   6657 idPhysics_AF::~idPhysics_AF
   6658 ================
   6659 */
   6660 idPhysics_AF::~idPhysics_AF() {
   6661 	int i;
   6662 
   6663 	trees.DeleteContents( true );
   6664 
   6665 	for ( i = 0; i < bodies.Num(); i++ ) {
   6666 		delete bodies[i];
   6667 	}
   6668 
   6669 	for ( i = 0; i < constraints.Num(); i++ ) {
   6670 		delete constraints[i];
   6671 	}
   6672 
   6673 	contactConstraints.SetNum( contactConstraints.NumAllocated() );
   6674 	for ( i = 0; i < contactConstraints.Num(); i++ ) {
   6675 		delete contactConstraints[i];
   6676 	}
   6677 
   6678 	delete lcp;
   6679 
   6680 	if ( masterBody ) {
   6681 		delete masterBody;
   6682 	}
   6683 }
   6684 
   6685 /*
   6686 ================
   6687 idPhysics_AF_SavePState
   6688 ================
   6689 */
   6690 void idPhysics_AF_SavePState( idSaveGame *saveFile, const AFPState_t &state ) {
   6691 	saveFile->WriteInt( state.atRest );
   6692 	saveFile->WriteFloat( state.noMoveTime );
   6693 	saveFile->WriteFloat( state.activateTime );
   6694 	saveFile->WriteFloat( state.lastTimeStep );
   6695 	saveFile->WriteVec6( state.pushVelocity );
   6696 }
   6697 
   6698 /*
   6699 ================
   6700 idPhysics_AF_RestorePState
   6701 ================
   6702 */
   6703 void idPhysics_AF_RestorePState( idRestoreGame *saveFile, AFPState_t &state ) {
   6704 	saveFile->ReadInt( state.atRest );
   6705 	saveFile->ReadFloat( state.noMoveTime );
   6706 	saveFile->ReadFloat( state.activateTime );
   6707 	saveFile->ReadFloat( state.lastTimeStep );
   6708 	saveFile->ReadVec6( state.pushVelocity );
   6709 }
   6710 
   6711 /*
   6712 ================
   6713 idPhysics_AF::Save
   6714 ================
   6715 */
   6716 void idPhysics_AF::Save( idSaveGame *saveFile ) const {
   6717 	int i;
   6718 
   6719 	// the articulated figure structure is handled by the owner
   6720 
   6721 	idPhysics_AF_SavePState( saveFile, current );
   6722 	idPhysics_AF_SavePState( saveFile, saved );
   6723 
   6724 	saveFile->WriteInt( bodies.Num() );
   6725 	for ( i = 0; i < bodies.Num(); i++ ) {
   6726 		bodies[i]->Save( saveFile );
   6727 	}
   6728 	if ( masterBody ) {
   6729 		saveFile->WriteBool( true );
   6730 		masterBody->Save( saveFile );
   6731 	} else {
   6732 		saveFile->WriteBool( false );
   6733 	}
   6734 
   6735 	saveFile->WriteInt( constraints.Num() );
   6736 	for ( i = 0; i < constraints.Num(); i++ ) {
   6737 		constraints[i]->Save( saveFile );
   6738 	}
   6739 
   6740 	saveFile->WriteBool( changedAF );
   6741 
   6742 	saveFile->WriteFloat( linearFriction );
   6743 	saveFile->WriteFloat( angularFriction );
   6744 	saveFile->WriteFloat( contactFriction );
   6745 	saveFile->WriteFloat( bouncyness );
   6746 	saveFile->WriteFloat( totalMass );
   6747 	saveFile->WriteFloat( forceTotalMass );
   6748 
   6749 	saveFile->WriteVec2( suspendVelocity );
   6750 	saveFile->WriteVec2( suspendAcceleration );
   6751 	saveFile->WriteFloat( noMoveTime );
   6752 	saveFile->WriteFloat( noMoveTranslation );
   6753 	saveFile->WriteFloat( noMoveRotation );
   6754 	saveFile->WriteFloat( minMoveTime );
   6755 	saveFile->WriteFloat( maxMoveTime );
   6756 	saveFile->WriteFloat( impulseThreshold );
   6757 
   6758 	saveFile->WriteFloat( timeScale );
   6759 	saveFile->WriteFloat( timeScaleRampStart );
   6760 	saveFile->WriteFloat( timeScaleRampEnd );
   6761 
   6762 	saveFile->WriteFloat( jointFrictionScale );
   6763 	saveFile->WriteFloat( jointFrictionDent );
   6764 	saveFile->WriteFloat( jointFrictionDentStart );
   6765 	saveFile->WriteFloat( jointFrictionDentEnd );
   6766 	saveFile->WriteFloat( jointFrictionDentScale );
   6767 
   6768 	saveFile->WriteFloat( contactFrictionScale );
   6769 	saveFile->WriteFloat( contactFrictionDent );
   6770 	saveFile->WriteFloat( contactFrictionDentStart );
   6771 	saveFile->WriteFloat( contactFrictionDentEnd );
   6772 	saveFile->WriteFloat( contactFrictionDentScale );
   6773 
   6774 	saveFile->WriteBool( enableCollision );
   6775 	saveFile->WriteBool( selfCollision );
   6776 	saveFile->WriteBool( comeToRest );
   6777 	saveFile->WriteBool( linearTime );
   6778 	saveFile->WriteBool( noImpact );
   6779 	saveFile->WriteBool( worldConstraintsLocked );
   6780 	saveFile->WriteBool( forcePushable );
   6781 }
   6782 
   6783 /*
   6784 ================
   6785 idPhysics_AF::Restore
   6786 ================
   6787 */
   6788 void idPhysics_AF::Restore( idRestoreGame *saveFile ) {
   6789 	int i, num;
   6790 	bool hasMaster;
   6791 
   6792 	// the articulated figure structure should have already been restored
   6793 
   6794 	idPhysics_AF_RestorePState( saveFile, current );
   6795 	idPhysics_AF_RestorePState( saveFile, saved );
   6796 
   6797 	saveFile->ReadInt( num );
   6798 	assert( num == bodies.Num() );
   6799 	for ( i = 0; i < bodies.Num(); i++ ) {
   6800 		bodies[i]->Restore( saveFile );
   6801 	}
   6802 	saveFile->ReadBool( hasMaster );
   6803 	if ( hasMaster ) {
   6804 		masterBody = new (TAG_PHYSICS_AF) idAFBody();
   6805 		masterBody->Restore( saveFile );
   6806 	}
   6807 
   6808 	saveFile->ReadInt( num );
   6809 	assert( num == constraints.Num() );
   6810 	for ( i = 0; i < constraints.Num(); i++ ) {
   6811 		constraints[i]->Restore( saveFile );
   6812 	}
   6813 
   6814 	saveFile->ReadBool( changedAF );
   6815 
   6816 	saveFile->ReadFloat( linearFriction );
   6817 	saveFile->ReadFloat( angularFriction );
   6818 	saveFile->ReadFloat( contactFriction );
   6819 	saveFile->ReadFloat( bouncyness );
   6820 	saveFile->ReadFloat( totalMass );
   6821 	saveFile->ReadFloat( forceTotalMass );
   6822 
   6823 	saveFile->ReadVec2( suspendVelocity );
   6824 	saveFile->ReadVec2( suspendAcceleration );
   6825 	saveFile->ReadFloat( noMoveTime );
   6826 	saveFile->ReadFloat( noMoveTranslation );
   6827 	saveFile->ReadFloat( noMoveRotation );
   6828 	saveFile->ReadFloat( minMoveTime );
   6829 	saveFile->ReadFloat( maxMoveTime );
   6830 	saveFile->ReadFloat( impulseThreshold );
   6831 
   6832 	saveFile->ReadFloat( timeScale );
   6833 	saveFile->ReadFloat( timeScaleRampStart );
   6834 	saveFile->ReadFloat( timeScaleRampEnd );
   6835 
   6836 	saveFile->ReadFloat( jointFrictionScale );
   6837 	saveFile->ReadFloat( jointFrictionDent );
   6838 	saveFile->ReadFloat( jointFrictionDentStart );
   6839 	saveFile->ReadFloat( jointFrictionDentEnd );
   6840 	saveFile->ReadFloat( jointFrictionDentScale );
   6841 
   6842 	saveFile->ReadFloat( contactFrictionScale );
   6843 	saveFile->ReadFloat( contactFrictionDent );
   6844 	saveFile->ReadFloat( contactFrictionDentStart );
   6845 	saveFile->ReadFloat( contactFrictionDentEnd );
   6846 	saveFile->ReadFloat( contactFrictionDentScale );
   6847 
   6848 	saveFile->ReadBool( enableCollision );
   6849 	saveFile->ReadBool( selfCollision );
   6850 	saveFile->ReadBool( comeToRest );
   6851 	saveFile->ReadBool( linearTime );
   6852 	saveFile->ReadBool( noImpact );
   6853 	saveFile->ReadBool( worldConstraintsLocked );
   6854 	saveFile->ReadBool( forcePushable );
   6855 
   6856 	changedAF = true;
   6857 
   6858 	UpdateClipModels();
   6859 }
   6860 
   6861 /*
   6862 ================
   6863 idPhysics_AF::IsClosedLoop
   6864 ================
   6865 */
   6866 bool idPhysics_AF::IsClosedLoop( const idAFBody *body1, const idAFBody *body2 ) const {
   6867 	const idAFBody *b1, *b2;
   6868 
   6869 	for ( b1 = body1; b1->parent; b1 = b1->parent ) {
   6870 	}
   6871 	for ( b2 = body2; b2->parent; b2 = b2->parent ) {
   6872 	}
   6873 	return ( b1 == b2 );
   6874 }
   6875 
   6876 /*
   6877 ================
   6878 idPhysics_AF::BuildTrees
   6879 ================
   6880 */
   6881 void idPhysics_AF::BuildTrees() {
   6882 	int i;
   6883 	float scale;
   6884 	idAFBody *b;
   6885 	idAFConstraint *c;
   6886 	idAFTree *tree;
   6887 
   6888 	primaryConstraints.Clear();
   6889 	auxiliaryConstraints.Clear();
   6890 	trees.DeleteContents( true );
   6891 
   6892 	totalMass = 0.0f;
   6893 	for ( i = 0; i < bodies.Num(); i++ ) {
   6894 		b = bodies[i];
   6895 		b->parent = NULL;
   6896 		b->primaryConstraint = NULL;
   6897 		b->constraints.SetNum( 0 );
   6898 		b->children.Clear();
   6899 		b->tree = NULL;
   6900 		totalMass += b->mass;
   6901 	}
   6902 
   6903 	if ( forceTotalMass > 0.0f ) {
   6904 		scale = forceTotalMass / totalMass;
   6905 		for ( i = 0; i < bodies.Num(); i++ ) {
   6906 			b = bodies[i];
   6907 			b->mass *= scale;
   6908 			b->invMass = 1.0f / b->mass;
   6909 			b->inertiaTensor *= scale;
   6910 			b->inverseInertiaTensor = b->inertiaTensor.Inverse();
   6911 		}
   6912 		totalMass = forceTotalMass;
   6913 	}
   6914 
   6915 	if ( af_useLinearTime.GetBool() ) {
   6916 
   6917 		for ( i = 0; i < constraints.Num(); i++ ) {
   6918 			c = constraints[i];
   6919 
   6920 			c->body1->constraints.Append( c );
   6921 			if ( c->body2 ) {
   6922 				c->body2->constraints.Append( c );
   6923 			}
   6924 
   6925 			// only bilateral constraints between two non-world bodies that do not
   6926 			// create loops can be used as primary constraints
   6927 			if ( !c->body1->primaryConstraint && c->fl.allowPrimary && c->body2 != NULL && !IsClosedLoop( c->body1, c->body2 ) ) {
   6928 				c->body1->primaryConstraint = c;
   6929 				c->body1->parent = c->body2;
   6930 				c->body2->children.Append( c->body1 );
   6931 				c->fl.isPrimary = true;
   6932 				c->firstIndex = 0;
   6933 				primaryConstraints.Append( c );
   6934 			} else {
   6935 				c->fl.isPrimary = false;
   6936 				auxiliaryConstraints.Append( c );
   6937 			}
   6938 		}
   6939 
   6940 		// create trees for all parent bodies
   6941 		for ( i = 0; i < bodies.Num(); i++ ) {
   6942 			if ( !bodies[i]->parent ) {
   6943 				tree = new (TAG_PHYSICS_AF) idAFTree();
   6944 				tree->sortedBodies.Clear();
   6945 				tree->sortedBodies.Append( bodies[i] );
   6946 				bodies[i]->tree = tree;
   6947 				trees.Append( tree );
   6948 			}
   6949 		}
   6950 
   6951 		// add each child body to the appropriate tree
   6952 		for ( i = 0; i < bodies.Num(); i++ ) {
   6953 			if ( bodies[i]->parent ) {
   6954 				for ( b = bodies[i]->parent; !b->tree; b = b->parent ) {
   6955 				}
   6956 				b->tree->sortedBodies.Append( bodies[i] );
   6957 				bodies[i]->tree = b->tree;
   6958 			}
   6959 		}
   6960 
   6961 		if ( trees.Num() > 1 ) {
   6962 			gameLocal.Warning( "Articulated figure has multiple seperate tree structures for entity '%s' type '%s'.",
   6963 								self->name.c_str(), self->GetType()->classname );
   6964 		}
   6965 
   6966 		// sort bodies in each tree to make sure parents come first
   6967 		for ( i = 0; i < trees.Num(); i++ ) {
   6968 			trees[i]->SortBodies();
   6969 		}
   6970 
   6971 	} else {
   6972 
   6973 		// create a tree for each body
   6974 		for ( i = 0; i < bodies.Num(); i++ ) {
   6975 			tree = new (TAG_PHYSICS_AF) idAFTree();
   6976 			tree->sortedBodies.Clear();
   6977 			tree->sortedBodies.Append( bodies[i] );
   6978 			bodies[i]->tree = tree;
   6979 			trees.Append( tree );
   6980 		}
   6981 
   6982 		for ( i = 0; i < constraints.Num(); i++ ) {
   6983 			c = constraints[i];
   6984 
   6985 			c->body1->constraints.Append( c );
   6986 			if ( c->body2 ) {
   6987 				c->body2->constraints.Append( c );
   6988 			}
   6989 
   6990 			c->fl.isPrimary = false;
   6991 			auxiliaryConstraints.Append( c );
   6992 		}
   6993 	}
   6994 }
   6995 
   6996 /*
   6997 ================
   6998 idPhysics_AF::AddBody
   6999 
   7000   bodies get an id in the order they are added starting at zero
   7001   as such the first body added will get id zero
   7002 ================
   7003 */
   7004 int idPhysics_AF::AddBody( idAFBody *body ) {
   7005 	int id = 0;
   7006 
   7007 	if ( body->clipModel == NULL ) {
   7008 		gameLocal.Error( "idPhysics_AF::AddBody: body '%s' has no clip model.", body->name.c_str() );
   7009 		return 0;
   7010 	}
   7011 
   7012 	if ( bodies.Find( body ) ) {
   7013 		gameLocal.Error( "idPhysics_AF::AddBody: body '%s' added twice.", body->name.c_str() );
   7014 	}
   7015 
   7016 	if ( GetBody( body->name ) ) {
   7017 		gameLocal.Error( "idPhysics_AF::AddBody: a body with the name '%s' already exists.", body->name.c_str() );
   7018 	}
   7019 
   7020 	id = bodies.Num();
   7021 	body->clipModel->SetId( id );
   7022 	if ( body->linearFriction < 0.0f ) {
   7023 		body->linearFriction = linearFriction;
   7024 		body->angularFriction = angularFriction;
   7025 		body->contactFriction = contactFriction;
   7026 	}
   7027 	if ( body->bouncyness < 0.0f ) {
   7028 		body->bouncyness = bouncyness;
   7029 	}
   7030 	if ( !body->fl.clipMaskSet ) {
   7031 		body->clipMask = clipMask;
   7032 	}
   7033 
   7034 	bodies.Append( body );
   7035 
   7036 	changedAF = true;
   7037 
   7038 	return id;
   7039 }
   7040 
   7041 /*
   7042 ================
   7043 idPhysics_AF::AddConstraint
   7044 ================
   7045 */
   7046 void idPhysics_AF::AddConstraint( idAFConstraint *constraint ) {
   7047 
   7048 	if ( constraints.Find( constraint ) ) {
   7049 		gameLocal.Error( "idPhysics_AF::AddConstraint: constraint '%s' added twice.", constraint->name.c_str() );
   7050 	}
   7051 	if ( GetConstraint( constraint->name ) ) {
   7052 		gameLocal.Error( "idPhysics_AF::AddConstraint: a constraint with the name '%s' already exists.", constraint->name.c_str() );
   7053 	}
   7054 	if ( !constraint->body1 ) {
   7055 		gameLocal.Error( "idPhysics_AF::AddConstraint: body1 == NULL on constraint '%s'.", constraint->name.c_str() );
   7056 	}
   7057 	if ( !bodies.Find( constraint->body1 ) ) {
   7058 		gameLocal.Error( "idPhysics_AF::AddConstraint: body1 of constraint '%s' is not part of the articulated figure.", constraint->name.c_str() );
   7059 	}
   7060 	if ( constraint->body2 && !bodies.Find( constraint->body2 ) ) {
   7061 		gameLocal.Error( "idPhysics_AF::AddConstraint: body2 of constraint '%s' is not part of the articulated figure.", constraint->name.c_str() );
   7062 	}
   7063 	if ( constraint->body1 == constraint->body2 ) {
   7064 		gameLocal.Error( "idPhysics_AF::AddConstraint: body1 and body2 of constraint '%s' are the same.", constraint->name.c_str() );
   7065 	}
   7066 
   7067 	constraints.Append( constraint );
   7068 	constraint->physics = this;
   7069 
   7070 	changedAF = true;
   7071 }
   7072 
   7073 /*
   7074 ================
   7075 idPhysics_AF::AddFrameConstraint
   7076 ================
   7077 */
   7078 void idPhysics_AF::AddFrameConstraint( idAFConstraint *constraint ) {
   7079 	frameConstraints.Append( constraint );
   7080 	constraint->physics = this;
   7081 }
   7082 
   7083 /*
   7084 ================
   7085 idPhysics_AF::ForceBodyId
   7086 ================
   7087 */
   7088 void idPhysics_AF::ForceBodyId( idAFBody *body, int newId ) {
   7089 	int id;
   7090 
   7091 	id = bodies.FindIndex( body );
   7092 	if ( id == -1 ) {
   7093 		gameLocal.Error( "ForceBodyId: body '%s' is not part of the articulated figure.\n", body->name.c_str() );
   7094 	}
   7095 	if ( id != newId ) {
   7096 		idAFBody *b = bodies[newId];
   7097 		bodies[newId] = bodies[id];
   7098 		bodies[id] = b;
   7099 		changedAF = true;
   7100 	}
   7101 }
   7102 
   7103 /*
   7104 ================
   7105 idPhysics_AF::GetBodyId
   7106 ================
   7107 */
   7108 int idPhysics_AF::GetBodyId( idAFBody *body ) const {
   7109 	int id;
   7110 
   7111 	id = bodies.FindIndex( body );
   7112 	if ( id == -1 && body ) {
   7113 		gameLocal.Error( "GetBodyId: body '%s' is not part of the articulated figure.\n", body->name.c_str() );
   7114 	}
   7115 	return id;
   7116 }
   7117 
   7118 /*
   7119 ================
   7120 idPhysics_AF::GetBodyId
   7121 ================
   7122 */
   7123 int idPhysics_AF::GetBodyId( const char *bodyName ) const {
   7124 	int i;
   7125 
   7126 	for ( i = 0; i < bodies.Num(); i++ ) {
   7127 		if ( !bodies[i]->name.Icmp( bodyName ) ) {
   7128 			return i;
   7129 		}
   7130 	}
   7131 	gameLocal.Error( "GetBodyId: no body with the name '%s' is not part of the articulated figure.\n", bodyName );
   7132 	return 0;
   7133 }
   7134 
   7135 /*
   7136 ================
   7137 idPhysics_AF::GetConstraintId
   7138 ================
   7139 */
   7140 int idPhysics_AF::GetConstraintId( idAFConstraint *constraint ) const {
   7141 	int id;
   7142 
   7143 	id = constraints.FindIndex( constraint );
   7144 	if ( id == -1 && constraint ) {
   7145 		gameLocal.Error( "GetConstraintId: constraint '%s' is not part of the articulated figure.\n", constraint->name.c_str() );
   7146 	}
   7147 	return id;
   7148 }
   7149 
   7150 /*
   7151 ================
   7152 idPhysics_AF::GetConstraintId
   7153 ================
   7154 */
   7155 int idPhysics_AF::GetConstraintId( const char *constraintName ) const {
   7156 	int i;
   7157 
   7158 	for ( i = 0; i < constraints.Num(); i++ ) {
   7159 		if ( constraints[i]->name.Icmp( constraintName ) == 0 ) {
   7160 			return i;
   7161 		}
   7162 	}
   7163 	gameLocal.Error( "GetConstraintId: no constraint with the name '%s' is not part of the articulated figure.\n", constraintName );
   7164 	return 0;
   7165 }
   7166 
   7167 /*
   7168 ================
   7169 idPhysics_AF::GetNumBodies
   7170 ================
   7171 */
   7172 int idPhysics_AF::GetNumBodies() const {
   7173 	return bodies.Num();
   7174 }
   7175 
   7176 /*
   7177 ================
   7178 idPhysics_AF::GetNumConstraints
   7179 ================
   7180 */
   7181 int idPhysics_AF::GetNumConstraints() const {
   7182 	return constraints.Num();
   7183 }
   7184 
   7185 /*
   7186 ================
   7187 idPhysics_AF::GetBody
   7188 ================
   7189 */
   7190 idAFBody *idPhysics_AF::GetBody( const char *bodyName ) const {
   7191 	int i;
   7192 
   7193 	for ( i = 0; i < bodies.Num(); i++ ) {
   7194 		if ( !bodies[i]->name.Icmp( bodyName ) ) {
   7195 			return bodies[i];
   7196 		}
   7197 	}
   7198 
   7199 	return NULL;
   7200 }
   7201 
   7202 /*
   7203 ================
   7204 idPhysics_AF::GetBody
   7205 ================
   7206 */
   7207 idAFBody *idPhysics_AF::GetBody( const int id ) const {
   7208 	if ( id < 0 || id >= bodies.Num() ) {
   7209 		gameLocal.Error( "GetBody: no body with id %d exists\n", id );
   7210 		return NULL;
   7211 	}
   7212 	return bodies[id];
   7213 }
   7214 
   7215 /*
   7216 ================
   7217 idPhysics_AF::GetConstraint
   7218 ================
   7219 */
   7220 idAFConstraint *idPhysics_AF::GetConstraint( const char *constraintName ) const {
   7221 	int i;
   7222 
   7223 	for ( i = 0; i < constraints.Num(); i++ ) {
   7224 		if ( constraints[i]->name.Icmp( constraintName ) == 0 ) {
   7225 			return constraints[i];
   7226 		}
   7227 	}
   7228 
   7229 	return NULL;
   7230 }
   7231 
   7232 /*
   7233 ================
   7234 idPhysics_AF::GetConstraint
   7235 ================
   7236 */
   7237 idAFConstraint *idPhysics_AF::GetConstraint( const int id ) const {
   7238 	if ( id < 0 || id >= constraints.Num() ) {
   7239 		gameLocal.Error( "GetConstraint: no constraint with id %d exists\n", id );
   7240 		return NULL;
   7241 	}
   7242 	return constraints[id];
   7243 }
   7244 
   7245 /*
   7246 ================
   7247 idPhysics_AF::DeleteBody
   7248 ================
   7249 */
   7250 void idPhysics_AF::DeleteBody( const char *bodyName ) {
   7251 	int i;
   7252 
   7253 	// find the body with the given name
   7254 	for ( i = 0; i < bodies.Num(); i++ ) {
   7255 		if ( !bodies[i]->name.Icmp( bodyName ) ) {
   7256 			break;
   7257 		}
   7258 	}
   7259 
   7260 	if ( i >= bodies.Num() ) {
   7261 		gameLocal.Warning( "DeleteBody: no body found in the articulated figure with the name '%s' for entity '%s' type '%s'.",
   7262 							bodyName, self->name.c_str(), self->GetType()->classname );
   7263 		return;
   7264 	}
   7265 
   7266 	DeleteBody( i );
   7267 }
   7268 
   7269 /*
   7270 ================
   7271 idPhysics_AF::DeleteBody
   7272 ================
   7273 */
   7274 void idPhysics_AF::DeleteBody( const int id ) {
   7275 	int j;
   7276 
   7277 	if ( id < 0 || id > bodies.Num() ) {
   7278 		gameLocal.Error( "DeleteBody: no body with id %d.", id );
   7279 		return;
   7280 	}
   7281 
   7282 	// remove any constraints attached to this body
   7283 	for ( j = 0; j < constraints.Num(); j++ ) {
   7284 		if ( constraints[j]->body1 == bodies[id] || constraints[j]->body2 == bodies[id] ) {
   7285 			delete constraints[j];
   7286 			constraints.RemoveIndex( j );
   7287 			j--;
   7288 		}
   7289 	}
   7290 
   7291 	// remove the body
   7292 	delete bodies[id];
   7293 	bodies.RemoveIndex( id );
   7294 
   7295 	// set new body ids
   7296 	for ( j = 0; j < bodies.Num(); j++ ) {
   7297 		bodies[j]->clipModel->SetId( j );
   7298 	}
   7299 
   7300 	changedAF = true;
   7301 }
   7302 
   7303 /*
   7304 ================
   7305 idPhysics_AF::DeleteConstraint
   7306 ================
   7307 */
   7308 void idPhysics_AF::DeleteConstraint( const char *constraintName ) {
   7309 	int i;
   7310 
   7311 	// find the constraint with the given name
   7312 	for ( i = 0; i < constraints.Num(); i++ ) {
   7313 		if ( !constraints[i]->name.Icmp( constraintName ) ) {
   7314 			break;
   7315 		}
   7316 	}
   7317 
   7318 	if ( i >= constraints.Num() ) {
   7319 		gameLocal.Warning( "DeleteConstraint: no constriant found in the articulated figure with the name '%s' for entity '%s' type '%s'.",
   7320 							constraintName, self->name.c_str(), self->GetType()->classname );
   7321 		return;
   7322 	}
   7323 
   7324 	DeleteConstraint( i );
   7325 }
   7326 
   7327 /*
   7328 ================
   7329 idPhysics_AF::DeleteConstraint
   7330 ================
   7331 */
   7332 void idPhysics_AF::DeleteConstraint( const int id ) {
   7333 
   7334 	if ( id < 0 || id >= constraints.Num() ) {
   7335 		gameLocal.Error( "DeleteConstraint: no constraint with id %d.", id );
   7336 		return;
   7337 	}
   7338 
   7339 	// remove the constraint
   7340 	delete constraints[id];
   7341 	constraints.RemoveIndex( id );
   7342 
   7343 	changedAF = true;
   7344 }
   7345 
   7346 /*
   7347 ================
   7348 idPhysics_AF::GetBodyContactConstraints
   7349 ================
   7350 */
   7351 int idPhysics_AF::GetBodyContactConstraints( const int id, idAFConstraint_Contact *contacts[], int maxContacts ) const {
   7352 	int i, numContacts;
   7353 	idAFBody *body;
   7354 	idAFConstraint_Contact *contact;
   7355 
   7356 	if ( id < 0 || id >= bodies.Num() || maxContacts <= 0 ) {
   7357 		return 0;
   7358 	}
   7359 
   7360 	numContacts = 0;
   7361 	body = bodies[id];
   7362 	for ( i = 0; i < contactConstraints.Num(); i++ ) {
   7363 		contact = contactConstraints[i];
   7364 		if ( contact->body1 == body || contact->body2 == body ) {
   7365 			contacts[numContacts++] = contact;
   7366 			if ( numContacts >= maxContacts ) {
   7367 				return numContacts;
   7368 			}
   7369 		}
   7370 	}
   7371 	return numContacts;
   7372 }
   7373 
   7374 /*
   7375 ================
   7376 idPhysics_AF::SetDefaultFriction
   7377 ================
   7378 */
   7379 void idPhysics_AF::SetDefaultFriction( float linear, float angular, float contact ) {
   7380 	if (	linear < 0.0f || linear > 1.0f ||
   7381 			angular < 0.0f || angular > 1.0f ||
   7382 			contact < 0.0f || contact > 1.0f ) {
   7383 		return;
   7384 	}
   7385 	linearFriction = linear;
   7386 	angularFriction = angular;
   7387 	contactFriction = contact;
   7388 }
   7389 
   7390 /*
   7391 ================
   7392 idPhysics_AF::GetImpactInfo
   7393 ================
   7394 */
   7395 void idPhysics_AF::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
   7396 	if ( id < 0 || id >= bodies.Num() ) {
   7397 		memset( info, 0, sizeof( *info ) );
   7398 		return;
   7399 	}
   7400 	info->invMass = 1.0f / bodies[id]->mass;
   7401 	info->invInertiaTensor = bodies[id]->current->worldAxis.Transpose() * bodies[id]->inverseInertiaTensor * bodies[id]->current->worldAxis;
   7402 	info->position = point - bodies[id]->current->worldOrigin;
   7403 	info->velocity = bodies[id]->current->spatialVelocity.SubVec3(0) + bodies[id]->current->spatialVelocity.SubVec3(1).Cross( info->position );
   7404 }
   7405 
   7406 /*
   7407 ================
   7408 idPhysics_AF::ApplyImpulse
   7409 ================
   7410 */
   7411 void idPhysics_AF::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
   7412 	if ( id < 0 || id >= bodies.Num() ) {
   7413 		return;
   7414 	}
   7415 	if ( noImpact || impulse.LengthSqr() < Square( impulseThreshold ) ) {
   7416 		return;
   7417 	}
   7418 	const float maxImpulse =  100000.0f;
   7419 	const float maxRotation = 100000.0f;
   7420 	idMat3 invWorldInertiaTensor = bodies[id]->current->worldAxis.Transpose() * bodies[id]->inverseInertiaTensor * bodies[id]->current->worldAxis;
   7421 	bodies[id]->current->spatialVelocity.SubVec3(0) += bodies[id]->invMass * impulse.Truncate( maxImpulse );
   7422 	bodies[id]->current->spatialVelocity.SubVec3(1) += invWorldInertiaTensor * (point - bodies[id]->current->worldOrigin).Cross( impulse ).Truncate( maxRotation );
   7423 	Activate();
   7424 }
   7425 
   7426 /*
   7427 ================
   7428 idPhysics_AF::AddForce
   7429 ================
   7430 */
   7431 void idPhysics_AF::AddForce( const int id, const idVec3 &point, const idVec3 &force ) {
   7432 	if ( noImpact ) {
   7433 		return;
   7434 	}
   7435 	if ( id < 0 || id >= bodies.Num() ) {
   7436 		return;
   7437 	}
   7438 	bodies[id]->current->externalForce.SubVec3( 0 ) += force;
   7439 	bodies[id]->current->externalForce.SubVec3( 1 ) += (point - bodies[id]->current->worldOrigin).Cross( force );
   7440 	Activate();
   7441 }
   7442 
   7443 /*
   7444 ================
   7445 idPhysics_AF::IsAtRest
   7446 ================
   7447 */
   7448 bool idPhysics_AF::IsAtRest() const {
   7449 	return current.atRest >= 0;
   7450 }
   7451 
   7452 /*
   7453 ================
   7454 idPhysics_AF::GetRestStartTime
   7455 ================
   7456 */
   7457 int idPhysics_AF::GetRestStartTime() const {
   7458 	return current.atRest;
   7459 }
   7460 
   7461 /*
   7462 ================
   7463 idPhysics_AF::IsPushable
   7464 ================
   7465 */
   7466 bool idPhysics_AF::IsPushable() const {
   7467 	return ( !noImpact && ( masterBody == NULL || forcePushable ) );
   7468 }
   7469 
   7470 /*
   7471 ================
   7472 idPhysics_AF::SaveState
   7473 ================
   7474 */
   7475 void idPhysics_AF::SaveState() {
   7476 	int i;
   7477 
   7478 	saved = current;
   7479 
   7480 	for ( i = 0; i < bodies.Num(); i++ ) {
   7481 		memcpy( &bodies[i]->saved, bodies[i]->current, sizeof( AFBodyPState_t ) );
   7482 	}
   7483 }
   7484 
   7485 /*
   7486 ================
   7487 idPhysics_AF::RestoreState
   7488 ================
   7489 */
   7490 void idPhysics_AF::RestoreState() {
   7491 	int i;
   7492 
   7493 	current = saved;
   7494 
   7495 	for ( i = 0; i < bodies.Num(); i++ ) {
   7496 		*(bodies[i]->current) = bodies[i]->saved;
   7497 	}
   7498 
   7499 	EvaluateContacts();
   7500 }
   7501 
   7502 /*
   7503 ================
   7504 idPhysics_AF::SetOrigin
   7505 ================
   7506 */
   7507 void idPhysics_AF::SetOrigin( const idVec3 &newOrigin, int id ) {
   7508 	if ( masterBody ) {
   7509 		Translate( masterBody->current->worldOrigin + masterBody->current->worldAxis * newOrigin - bodies[0]->current->worldOrigin );
   7510 	} else {
   7511 		Translate( newOrigin - bodies[0]->current->worldOrigin );
   7512 	}
   7513 }
   7514 
   7515 /*
   7516 ================
   7517 idPhysics_AF::SetAxis
   7518 ================
   7519 */
   7520 void idPhysics_AF::SetAxis( const idMat3 &newAxis, int id ) {
   7521 	idMat3 axis;
   7522 	idRotation rotation;
   7523 
   7524 	if ( masterBody ) {
   7525 		axis = bodies[0]->current->worldAxis.Transpose() * ( newAxis * masterBody->current->worldAxis );
   7526 	} else {
   7527 		axis = bodies[0]->current->worldAxis.Transpose() * newAxis;
   7528 	}
   7529 	rotation = axis.ToRotation();
   7530 	rotation.SetOrigin( bodies[0]->current->worldOrigin );
   7531 
   7532 	Rotate( rotation );
   7533 }
   7534 
   7535 /*
   7536 ================
   7537 idPhysics_AF::Translate
   7538 ================
   7539 */
   7540 void idPhysics_AF::Translate( const idVec3 &translation, int id ) {
   7541 	int i;
   7542 	idAFBody *body;
   7543 
   7544 	if ( !worldConstraintsLocked ) {
   7545 		// translate constraints attached to the world
   7546 		for ( i = 0; i < constraints.Num(); i++ ) {
   7547 			constraints[i]->Translate( translation );
   7548 		}
   7549 	}
   7550 
   7551 	// translate all the bodies
   7552 	for ( i = 0; i < bodies.Num(); i++ ) {
   7553 
   7554 		body = bodies[i];
   7555 		body->current->worldOrigin += translation;
   7556 	}
   7557 
   7558 	Activate();
   7559 
   7560 	UpdateClipModels();
   7561 }
   7562 
   7563 /*
   7564 ================
   7565 idPhysics_AF::Rotate
   7566 ================
   7567 */
   7568 void idPhysics_AF::Rotate( const idRotation &rotation, int id ) {
   7569 	int i;
   7570 	idAFBody *body;
   7571 
   7572 	if ( !worldConstraintsLocked ) {
   7573 		// rotate constraints attached to the world
   7574 		for ( i = 0; i < constraints.Num(); i++ ) {
   7575 			constraints[i]->Rotate( rotation );
   7576 		}
   7577 	}
   7578 
   7579 	// rotate all the bodies
   7580 	for ( i = 0; i < bodies.Num(); i++ ) {
   7581 		body = bodies[i];
   7582 
   7583 		body->current->worldOrigin *= rotation;
   7584 		body->current->worldAxis *= rotation.ToMat3();
   7585 	}
   7586 
   7587 	Activate();
   7588 
   7589 	UpdateClipModels();
   7590 }
   7591 
   7592 /*
   7593 ================
   7594 idPhysics_AF::GetOrigin
   7595 ================
   7596 */
   7597 const idVec3 &idPhysics_AF::GetOrigin( int id ) const {
   7598 	if ( id < 0 || id >= bodies.Num() ) {
   7599 		return vec3_origin;
   7600 	}
   7601 	else {
   7602 		return bodies[id]->current->worldOrigin;
   7603 	}
   7604 }
   7605 
   7606 /*
   7607 ================
   7608 idPhysics_AF::GetAxis
   7609 ================
   7610 */
   7611 const idMat3 &idPhysics_AF::GetAxis( int id ) const {
   7612 	if ( id < 0 || id >= bodies.Num() ) {
   7613 		return mat3_identity;
   7614 	}
   7615 	else {
   7616 		return bodies[id]->current->worldAxis;
   7617 	}
   7618 }
   7619 
   7620 /*
   7621 ================
   7622 idPhysics_AF::SetLinearVelocity
   7623 ================
   7624 */
   7625 void idPhysics_AF::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
   7626 	if ( id < 0 || id >= bodies.Num() ) {
   7627 		return;
   7628 	}
   7629 	bodies[id]->current->spatialVelocity.SubVec3( 0 ) = newLinearVelocity;
   7630 	Activate();
   7631 }
   7632 
   7633 /*
   7634 ================
   7635 idPhysics_AF::SetAngularVelocity
   7636 ================
   7637 */
   7638 void idPhysics_AF::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
   7639 	if ( id < 0 || id >= bodies.Num() ) {
   7640 		return;
   7641 	}
   7642 	bodies[id]->current->spatialVelocity.SubVec3( 1 ) = newAngularVelocity;
   7643 	Activate();
   7644 }
   7645 
   7646 /*
   7647 ================
   7648 idPhysics_AF::GetLinearVelocity
   7649 ================
   7650 */
   7651 const idVec3 &idPhysics_AF::GetLinearVelocity( int id ) const {
   7652 	if ( id < 0 || id >= bodies.Num() ) {
   7653 		return vec3_origin;
   7654 	}
   7655 	else {
   7656 		return bodies[id]->current->spatialVelocity.SubVec3( 0 );
   7657 	}
   7658 }
   7659 
   7660 /*
   7661 ================
   7662 idPhysics_AF::GetAngularVelocity
   7663 ================
   7664 */
   7665 const idVec3 &idPhysics_AF::GetAngularVelocity( int id ) const {
   7666 	if ( id < 0 || id >= bodies.Num() ) {
   7667 		return vec3_origin;
   7668 	}
   7669 	else {
   7670 		return bodies[id]->current->spatialVelocity.SubVec3( 1 );
   7671 	}
   7672 }
   7673 
   7674 /*
   7675 ================
   7676 idPhysics_AF::ClipTranslation
   7677 ================
   7678 */
   7679 void idPhysics_AF::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
   7680 	int i;
   7681 	idAFBody *body;
   7682 	trace_t bodyResults;
   7683 
   7684 	results.fraction = 1.0f;
   7685 
   7686 	for ( i = 0; i < bodies.Num(); i++ ) {
   7687 		body = bodies[i];
   7688 
   7689 		if ( body->clipModel->IsTraceModel() ) {
   7690 			if ( model ) {
   7691 				gameLocal.clip.TranslationModel( bodyResults, body->current->worldOrigin, body->current->worldOrigin + translation,
   7692 									body->clipModel, body->current->worldAxis, body->clipMask,
   7693 										model->Handle(), model->GetOrigin(), model->GetAxis() );
   7694 			}
   7695 			else {
   7696 				gameLocal.clip.Translation( bodyResults, body->current->worldOrigin, body->current->worldOrigin + translation,
   7697 									body->clipModel, body->current->worldAxis, body->clipMask, self );
   7698 			}
   7699 			if ( bodyResults.fraction < results.fraction ) {
   7700 				results = bodyResults;
   7701 			}
   7702 		}
   7703 	}
   7704 
   7705 	results.endpos = bodies[0]->current->worldOrigin + results.fraction * translation;
   7706 	results.endAxis = bodies[0]->current->worldAxis;
   7707 }
   7708 
   7709 /*
   7710 ================
   7711 idPhysics_AF::ClipRotation
   7712 ================
   7713 */
   7714 void idPhysics_AF::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
   7715 	int i;
   7716 	idAFBody *body;
   7717 	trace_t bodyResults;
   7718 	idRotation partialRotation;
   7719 
   7720 	results.fraction = 1.0f;
   7721 
   7722 	for ( i = 0; i < bodies.Num(); i++ ) {
   7723 		body = bodies[i];
   7724 
   7725 		if ( body->clipModel->IsTraceModel() ) {
   7726 			if ( model ) {
   7727 				gameLocal.clip.RotationModel( bodyResults, body->current->worldOrigin, rotation,
   7728 									body->clipModel, body->current->worldAxis, body->clipMask,
   7729 										model->Handle(), model->GetOrigin(), model->GetAxis() );
   7730 			}
   7731 			else {
   7732 				gameLocal.clip.Rotation( bodyResults, body->current->worldOrigin, rotation,
   7733 									body->clipModel, body->current->worldAxis, body->clipMask, self );
   7734 			}
   7735 			if ( bodyResults.fraction < results.fraction ) {
   7736 				results = bodyResults;
   7737 			}
   7738 		}
   7739 	}
   7740 
   7741 	partialRotation = rotation * results.fraction;
   7742 	results.endpos = bodies[0]->current->worldOrigin * partialRotation;
   7743 	results.endAxis = bodies[0]->current->worldAxis * partialRotation.ToMat3();
   7744 }
   7745 
   7746 /*
   7747 ================
   7748 idPhysics_AF::ClipContents
   7749 ================
   7750 */
   7751 int idPhysics_AF::ClipContents( const idClipModel *model ) const {
   7752 	int i, contents;
   7753 	idAFBody *body;
   7754 
   7755 	contents = 0;
   7756 
   7757 	for ( i = 0; i < bodies.Num(); i++ ) {
   7758 		body = bodies[i];
   7759 
   7760 		if ( body->clipModel->IsTraceModel() ) {
   7761 			if ( model ) {
   7762 				contents |= gameLocal.clip.ContentsModel( body->current->worldOrigin,
   7763 									body->clipModel, body->current->worldAxis, -1,
   7764 										model->Handle(), model->GetOrigin(), model->GetAxis() );
   7765 			}
   7766 			else {
   7767 				contents |= gameLocal.clip.Contents( body->current->worldOrigin,
   7768 									body->clipModel, body->current->worldAxis, -1, NULL );
   7769 			}
   7770 		}
   7771 	}
   7772 
   7773 	return contents;
   7774 }
   7775 
   7776 /*
   7777 ================
   7778 idPhysics_AF::DisableClip
   7779 ================
   7780 */
   7781 void idPhysics_AF::DisableClip() {
   7782 	int i;
   7783 
   7784 	for ( i = 0; i < bodies.Num(); i++ ) {
   7785 		bodies[i]->clipModel->Disable();
   7786 	}
   7787 }
   7788 
   7789 /*
   7790 ================
   7791 idPhysics_AF::EnableClip
   7792 ================
   7793 */
   7794 void idPhysics_AF::EnableClip() {
   7795 	int i;
   7796 
   7797 	for ( i = 0; i < bodies.Num(); i++ ) {
   7798 		bodies[i]->clipModel->Enable();
   7799 	}
   7800 }
   7801 
   7802 /*
   7803 ================
   7804 idPhysics_AF::UnlinkClip
   7805 ================
   7806 */
   7807 void idPhysics_AF::UnlinkClip() {
   7808 	int i;
   7809 
   7810 	for ( i = 0; i < bodies.Num(); i++ ) {
   7811 		bodies[i]->clipModel->Unlink();
   7812 	}
   7813 }
   7814 
   7815 /*
   7816 ================
   7817 idPhysics_AF::LinkClip
   7818 ================
   7819 */
   7820 void idPhysics_AF::LinkClip() {
   7821 	UpdateClipModels();
   7822 }
   7823 
   7824 /*
   7825 ================
   7826 idPhysics_AF::SetPushed
   7827 ================
   7828 */
   7829 void idPhysics_AF::SetPushed( int deltaTime ) {
   7830 	idAFBody *body;
   7831 	idRotation rotation;
   7832 
   7833 	if ( bodies.Num() ) {
   7834 		body = bodies[0];
   7835 		rotation = ( body->saved.worldAxis.Transpose() * body->current->worldAxis ).ToRotation();
   7836 
   7837 		// velocity with which the af is pushed
   7838 		current.pushVelocity.SubVec3(0) += ( body->current->worldOrigin - body->saved.worldOrigin ) / ( deltaTime * idMath::M_MS2SEC );
   7839 		current.pushVelocity.SubVec3(1) += rotation.GetVec() * -DEG2RAD( rotation.GetAngle() ) / ( deltaTime * idMath::M_MS2SEC );
   7840 	}
   7841 }
   7842 
   7843 /*
   7844 ================
   7845 idPhysics_AF::GetPushedLinearVelocity
   7846 ================
   7847 */
   7848 const idVec3 &idPhysics_AF::GetPushedLinearVelocity( const int id ) const {
   7849 	return current.pushVelocity.SubVec3(0);
   7850 }
   7851 
   7852 /*
   7853 ================
   7854 idPhysics_AF::GetPushedAngularVelocity
   7855 ================
   7856 */
   7857 const idVec3 &idPhysics_AF::GetPushedAngularVelocity( const int id ) const {
   7858 	return current.pushVelocity.SubVec3(1);
   7859 }
   7860 
   7861 /*
   7862 ================
   7863 idPhysics_AF::SetMaster
   7864 
   7865    the binding is orientated based on the constraints being used
   7866 ================
   7867 */
   7868 void idPhysics_AF::SetMaster( idEntity *master, const bool orientated ) {
   7869 	int i;
   7870 	idVec3 masterOrigin;
   7871 	idMat3 masterAxis;
   7872 	idRotation rotation;
   7873 
   7874 	if ( master ) {
   7875 		self->GetMasterPosition( masterOrigin, masterAxis );
   7876 		if ( !masterBody ) {
   7877 			masterBody = new (TAG_PHYSICS_AF) idAFBody();
   7878 			// translate and rotate all the constraints with body2 == NULL from world space to master space
   7879 			rotation = masterAxis.Transpose().ToRotation();
   7880 			for ( i = 0; i < constraints.Num(); i++ ) {
   7881 				if ( constraints[i]->GetBody2() == NULL ) {
   7882 					constraints[i]->Translate( -masterOrigin );
   7883 					constraints[i]->Rotate( rotation );
   7884 				}
   7885 			}
   7886 			Activate();
   7887 		}
   7888 		masterBody->current->worldOrigin = masterOrigin;
   7889 		masterBody->current->worldAxis = masterAxis;
   7890 	}
   7891 	else {
   7892 		if ( masterBody ) {
   7893 			// translate and rotate all the constraints with body2 == NULL from master space to world space
   7894 			rotation = masterBody->current->worldAxis.ToRotation();
   7895 			for ( i = 0; i < constraints.Num(); i++ ) {
   7896 				if ( constraints[i]->GetBody2() == NULL ) {
   7897 					constraints[i]->Rotate( rotation );
   7898 					constraints[i]->Translate( masterBody->current->worldOrigin );
   7899 				}
   7900 			}
   7901 			delete masterBody;
   7902 			masterBody = NULL;
   7903 			Activate();
   7904 		}
   7905 	}
   7906 }
   7907 
   7908 
   7909 const float	AF_VELOCITY_MAX				= 16000;
   7910 const int	AF_VELOCITY_TOTAL_BITS		= 16;
   7911 const int	AF_VELOCITY_EXPONENT_BITS	= idMath::BitsForInteger( idMath::BitsForFloat( AF_VELOCITY_MAX ) ) + 1;
   7912 const int	AF_VELOCITY_MANTISSA_BITS	= AF_VELOCITY_TOTAL_BITS - 1 - AF_VELOCITY_EXPONENT_BITS;
   7913 const float	AF_FORCE_MAX				= 1e20f;
   7914 const int	AF_FORCE_TOTAL_BITS			= 16;
   7915 const int	AF_FORCE_EXPONENT_BITS		= idMath::BitsForInteger( idMath::BitsForFloat( AF_FORCE_MAX ) ) + 1;
   7916 const int	AF_FORCE_MANTISSA_BITS		= AF_FORCE_TOTAL_BITS - 1 - AF_FORCE_EXPONENT_BITS;
   7917 
   7918 /*
   7919 ================
   7920 idPhysics_AF::WriteToSnapshot
   7921 ================
   7922 */
   7923 void idPhysics_AF::WriteToSnapshot( idBitMsg &msg ) const {
   7924 	int i;
   7925 	idCQuat quat;
   7926 
   7927 	msg.WriteLong( current.atRest );
   7928 	msg.WriteFloat( current.noMoveTime );
   7929 	msg.WriteFloat( current.activateTime );
   7930 	msg.WriteDeltaFloat( 0.0f, current.pushVelocity[0], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7931 	msg.WriteDeltaFloat( 0.0f, current.pushVelocity[1], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7932 	msg.WriteDeltaFloat( 0.0f, current.pushVelocity[2], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7933 	msg.WriteDeltaFloat( 0.0f, current.pushVelocity[3], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7934 	msg.WriteDeltaFloat( 0.0f, current.pushVelocity[4], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7935 	msg.WriteDeltaFloat( 0.0f, current.pushVelocity[5], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7936 
   7937 	msg.WriteByte( bodies.Num() );
   7938 
   7939 	for ( i = 0; i < bodies.Num(); i++ ) {
   7940 		AFBodyPState_t *state = bodies[i]->current;
   7941 		quat = state->worldAxis.ToCQuat();
   7942 
   7943 		msg.WriteFloat( state->worldOrigin[0] );
   7944 		msg.WriteFloat( state->worldOrigin[1] );
   7945 		msg.WriteFloat( state->worldOrigin[2] );
   7946 		msg.WriteFloat( quat.x );
   7947 		msg.WriteFloat( quat.y );
   7948 		msg.WriteFloat( quat.z );
   7949 		msg.WriteDeltaFloat( 0.0f, state->spatialVelocity[0], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7950 		msg.WriteDeltaFloat( 0.0f, state->spatialVelocity[1], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7951 		msg.WriteDeltaFloat( 0.0f, state->spatialVelocity[2], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7952 		msg.WriteDeltaFloat( 0.0f, state->spatialVelocity[3], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7953 		msg.WriteDeltaFloat( 0.0f, state->spatialVelocity[4], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7954 		msg.WriteDeltaFloat( 0.0f, state->spatialVelocity[5], AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7955 /*		msg.WriteDeltaFloat( 0.0f, state->externalForce[0], AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   7956 		msg.WriteDeltaFloat( 0.0f, state->externalForce[1], AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   7957 		msg.WriteDeltaFloat( 0.0f, state->externalForce[2], AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   7958 		msg.WriteDeltaFloat( 0.0f, state->externalForce[3], AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   7959 		msg.WriteDeltaFloat( 0.0f, state->externalForce[4], AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   7960 		msg.WriteDeltaFloat( 0.0f, state->externalForce[5], AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   7961 */
   7962 	}
   7963 }
   7964 
   7965 /*
   7966 ================
   7967 idPhysics_AF::ReadFromSnapshot
   7968 ================
   7969 */
   7970 void idPhysics_AF::ReadFromSnapshot( const idBitMsg &msg ) {
   7971 	int i, num;
   7972 	idCQuat quat;
   7973 
   7974 	current.atRest = msg.ReadLong();
   7975 	current.noMoveTime = msg.ReadFloat();
   7976 	current.activateTime = msg.ReadFloat();
   7977 	current.pushVelocity[0] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7978 	current.pushVelocity[1] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7979 	current.pushVelocity[2] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7980 	current.pushVelocity[3] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7981 	current.pushVelocity[4] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7982 	current.pushVelocity[5] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7983 
   7984 	num = msg.ReadByte();
   7985 	assert( num == bodies.Num() );
   7986 
   7987 	for ( i = 0; i < bodies.Num(); i++ ) {
   7988 		AFBodyPState_t *state = bodies[i]->current;
   7989 
   7990 		state->worldOrigin[0] = msg.ReadFloat();
   7991 		state->worldOrigin[1] = msg.ReadFloat();
   7992 		state->worldOrigin[2] = msg.ReadFloat();
   7993 		quat.x = msg.ReadFloat();
   7994 		quat.y = msg.ReadFloat();
   7995 		quat.z = msg.ReadFloat();
   7996 		state->spatialVelocity[0] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7997 		state->spatialVelocity[1] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7998 		state->spatialVelocity[2] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   7999 		state->spatialVelocity[3] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   8000 		state->spatialVelocity[4] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   8001 		state->spatialVelocity[5] = msg.ReadDeltaFloat( 0.0f, AF_VELOCITY_EXPONENT_BITS, AF_VELOCITY_MANTISSA_BITS );
   8002 /*		state->externalForce[0] = msg.ReadDeltaFloat( 0.0f, AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   8003 		state->externalForce[1] = msg.ReadDeltaFloat( 0.0f, AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   8004 		state->externalForce[2] = msg.ReadDeltaFloat( 0.0f, AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   8005 		state->externalForce[3] = msg.ReadDeltaFloat( 0.0f, AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   8006 		state->externalForce[4] = msg.ReadDeltaFloat( 0.0f, AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   8007 		state->externalForce[5] = msg.ReadDeltaFloat( 0.0f, AF_FORCE_EXPONENT_BITS, AF_FORCE_MANTISSA_BITS );
   8008 */
   8009 		state->worldAxis = quat.ToMat3();
   8010 	}
   8011 
   8012 	UpdateClipModels();
   8013 }