1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "sys/platform.h"
30 #include "idlib/math/Quat.h"
31 
32 #include "gamesys/SysCvar.h"
33 #include "physics/Force.h"
34 #include "Entity.h"
35 
36 #include "physics/Physics_StaticMulti.h"
37 
38 CLASS_DECLARATION( idPhysics, idPhysics_StaticMulti )
39 END_CLASS
40 
41 staticPState_t defaultState;
42 
43 
44 /*
45 ================
46 idPhysics_StaticMulti::idPhysics_StaticMulti
47 ================
48 */
idPhysics_StaticMulti(void)49 idPhysics_StaticMulti::idPhysics_StaticMulti( void ) {
50 	self = NULL;
51 	hasMaster = false;
52 	isOrientated = false;
53 
54 	defaultState.origin.Zero();
55 	defaultState.axis.Identity();
56 	defaultState.localOrigin.Zero();
57 	defaultState.localAxis.Identity();
58 
59 	current.SetNum( 1 );
60 	current[0] = defaultState;
61 	clipModels.SetNum( 1 );
62 	clipModels[0] = NULL;
63 }
64 
65 /*
66 ================
67 idPhysics_StaticMulti::~idPhysics_StaticMulti
68 ================
69 */
~idPhysics_StaticMulti(void)70 idPhysics_StaticMulti::~idPhysics_StaticMulti( void ) {
71 	if ( self && self->GetPhysics() == this ) {
72 		self->SetPhysics( NULL );
73 	}
74 	idForce::DeletePhysics( this );
75 	for ( int i = 0; i < clipModels.Num(); i++ ) {
76 		delete clipModels[i];
77 	}
78 }
79 
80 /*
81 ================
82 idPhysics_StaticMulti::Save
83 ================
84 */
Save(idSaveGame * savefile) const85 void idPhysics_StaticMulti::Save( idSaveGame *savefile ) const {
86 	int i;
87 
88 	savefile->WriteObject( self );
89 
90 	savefile->WriteInt(current.Num());
91 	for  ( i = 0; i < current.Num(); i++ ) {
92 		savefile->WriteVec3( current[i].origin );
93 		savefile->WriteMat3( current[i].axis );
94 		savefile->WriteVec3( current[i].localOrigin );
95 		savefile->WriteMat3( current[i].localAxis );
96 	}
97 
98 	savefile->WriteInt( clipModels.Num() );
99 	for ( i = 0; i < clipModels.Num(); i++ ) {
100 		savefile->WriteClipModel( clipModels[i] );
101 	}
102 
103 	savefile->WriteBool(hasMaster);
104 	savefile->WriteBool(isOrientated);
105 }
106 
107 /*
108 ================
109 idPhysics_StaticMulti::Restore
110 ================
111 */
Restore(idRestoreGame * savefile)112 void idPhysics_StaticMulti::Restore( idRestoreGame *savefile ) {
113 	int i, num;
114 
115 	savefile->ReadObject( reinterpret_cast<idClass *&>( self ) );
116 
117 	savefile->ReadInt(num);
118 	current.AssureSize( num );
119 	for ( i = 0; i < num; i++ ) {
120 		savefile->ReadVec3( current[i].origin );
121 		savefile->ReadMat3( current[i].axis );
122 		savefile->ReadVec3( current[i].localOrigin );
123 		savefile->ReadMat3( current[i].localAxis );
124 	}
125 
126 	savefile->ReadInt(num);
127 	clipModels.SetNum( num );
128 	for ( i = 0; i < num; i++ ) {
129 		savefile->ReadClipModel( clipModels[i] );
130 	}
131 
132 	savefile->ReadBool(hasMaster);
133 	savefile->ReadBool(isOrientated);
134 }
135 
136 /*
137 ================
138 idPhysics_StaticMulti::SetSelf
139 ================
140 */
SetSelf(idEntity * e)141 void idPhysics_StaticMulti::SetSelf( idEntity *e ) {
142 	assert( e );
143 	self = e;
144 }
145 
146 /*
147 ================
148 idPhysics_StaticMulti::RemoveIndex
149 ================
150 */
RemoveIndex(int id,bool freeClipModel)151 void idPhysics_StaticMulti::RemoveIndex( int id, bool freeClipModel ) {
152 	if ( id < 0 || id >= clipModels.Num() ) {
153 		return;
154 	}
155 	if ( clipModels[id] && freeClipModel ) {
156 		delete clipModels[id];
157 		clipModels[id] = NULL;
158 	}
159 	clipModels.RemoveIndex( id );
160 	current.RemoveIndex( id );
161 }
162 
163 /*
164 ================
165 idPhysics_StaticMulti::SetClipModel
166 ================
167 */
SetClipModel(idClipModel * model,float density,int id,bool freeOld)168 void idPhysics_StaticMulti::SetClipModel( idClipModel *model, float density, int id, bool freeOld ) {
169 	int i;
170 
171 	assert( self );
172 
173 	if ( id >= clipModels.Num() ) {
174 		current.AssureSize( id+1, defaultState );
175 		clipModels.AssureSize( id+1, NULL );
176 	}
177 
178 	if ( clipModels[id] && clipModels[id] != model && freeOld ) {
179 		delete clipModels[id];
180 	}
181 	clipModels[id] = model;
182 	if ( clipModels[id] ) {
183 		clipModels[id]->Link( gameLocal.clip, self, id, current[id].origin, current[id].axis );
184 	}
185 
186 	for ( i = clipModels.Num() - 1; i >= 1; i-- ) {
187 		if ( clipModels[i] ) {
188 			break;
189 		}
190 	}
191 	current.SetNum( i+1, false );
192 	clipModels.SetNum( i+1, false );
193 }
194 
195 /*
196 ================
197 idPhysics_StaticMulti::GetClipModel
198 ================
199 */
GetClipModel(int id) const200 idClipModel *idPhysics_StaticMulti::GetClipModel( int id ) const {
201 	if ( id >= 0 && id < clipModels.Num() && clipModels[id] ) {
202 		return clipModels[id];
203 	}
204 	return gameLocal.clip.DefaultClipModel();
205 }
206 
207 /*
208 ================
209 idPhysics_StaticMulti::GetNumClipModels
210 ================
211 */
GetNumClipModels(void) const212 int idPhysics_StaticMulti::GetNumClipModels( void ) const {
213 	return clipModels.Num();
214 }
215 
216 /*
217 ================
218 idPhysics_StaticMulti::SetMass
219 ================
220 */
SetMass(float mass,int id)221 void idPhysics_StaticMulti::SetMass( float mass, int id ) {
222 }
223 
224 /*
225 ================
226 idPhysics_StaticMulti::GetMass
227 ================
228 */
GetMass(int id) const229 float idPhysics_StaticMulti::GetMass( int id ) const {
230 	return 0.0f;
231 }
232 
233 /*
234 ================
235 idPhysics_StaticMulti::SetContents
236 ================
237 */
SetContents(int contents,int id)238 void idPhysics_StaticMulti::SetContents( int contents, int id ) {
239 	int i;
240 
241 	if ( id >= 0 && id < clipModels.Num() ) {
242 		if ( clipModels[id] ) {
243 			clipModels[id]->SetContents( contents );
244 		}
245 	} else if ( id == -1 ) {
246 		for ( i = 0; i < clipModels.Num(); i++ ) {
247 			if ( clipModels[i] ) {
248 				clipModels[i]->SetContents( contents );
249 			}
250 		}
251 	}
252 }
253 
254 /*
255 ================
256 idPhysics_StaticMulti::GetContents
257 ================
258 */
GetContents(int id) const259 int idPhysics_StaticMulti::GetContents( int id ) const {
260 	int i, contents = 0;
261 
262 	if ( id >= 0 && id < clipModels.Num() ) {
263 		if ( clipModels[id] ) {
264 			contents = clipModels[id]->GetContents();
265 		}
266 	} else if ( id == -1 ) {
267 		for ( i = 0; i < clipModels.Num(); i++ ) {
268 			if ( clipModels[i] ) {
269 				contents |= clipModels[i]->GetContents();
270 			}
271 		}
272 	}
273 	return contents;
274 }
275 
276 /*
277 ================
278 idPhysics_StaticMulti::SetClipMask
279 ================
280 */
SetClipMask(int mask,int id)281 void idPhysics_StaticMulti::SetClipMask( int mask, int id ) {
282 }
283 
284 /*
285 ================
286 idPhysics_StaticMulti::GetClipMask
287 ================
288 */
GetClipMask(int id) const289 int idPhysics_StaticMulti::GetClipMask( int id ) const {
290 	return 0;
291 }
292 
293 /*
294 ================
295 idPhysics_StaticMulti::GetBounds
296 ================
297 */
GetBounds(int id) const298 const idBounds &idPhysics_StaticMulti::GetBounds( int id ) const {
299 	int i;
300 	static idBounds bounds;
301 
302 	if ( id >= 0 && id < clipModels.Num() ) {
303 		if ( clipModels[id] ) {
304 			return clipModels[id]->GetBounds();
305 		}
306 	}
307 	if ( id == -1 ) {
308 		bounds.Clear();
309 		for ( i = 0; i < clipModels.Num(); i++ ) {
310 			if ( clipModels[i] ) {
311 				bounds.AddBounds( clipModels[i]->GetAbsBounds() );
312 			}
313 		}
314 		for ( i = 0; i < clipModels.Num(); i++ ) {
315 			if ( clipModels[i] ) {
316 				bounds[0] -= clipModels[i]->GetOrigin();
317 				bounds[1] -= clipModels[i]->GetOrigin();
318 				break;
319 			}
320 		}
321 		return bounds;
322 	}
323 	return bounds_zero;
324 }
325 
326 /*
327 ================
328 idPhysics_StaticMulti::GetAbsBounds
329 ================
330 */
GetAbsBounds(int id) const331 const idBounds &idPhysics_StaticMulti::GetAbsBounds( int id ) const {
332 	int i;
333 	static idBounds absBounds;
334 
335 	if ( id >= 0 && id < clipModels.Num() ) {
336 		if ( clipModels[id] ) {
337 			return clipModels[id]->GetAbsBounds();
338 		}
339 	}
340 	if ( id == -1 ) {
341 		absBounds.Clear();
342 		for ( i = 0; i < clipModels.Num(); i++ ) {
343 			if ( clipModels[i] ) {
344 				absBounds.AddBounds( clipModels[i]->GetAbsBounds() );
345 			}
346 		}
347 		return absBounds;
348 	}
349 	return bounds_zero;
350 }
351 
352 /*
353 ================
354 idPhysics_StaticMulti::Evaluate
355 ================
356 */
Evaluate(int timeStepMSec,int endTimeMSec)357 bool idPhysics_StaticMulti::Evaluate( int timeStepMSec, int endTimeMSec ) {
358 	int i;
359 	idVec3 masterOrigin;
360 	idMat3 masterAxis;
361 
362 	if ( hasMaster ) {
363 		self->GetMasterPosition( masterOrigin, masterAxis );
364 		for ( i = 0; i < clipModels.Num(); i++ ) {
365 			current[i].origin = masterOrigin + current[i].localOrigin * masterAxis;
366 			if ( isOrientated ) {
367 				current[i].axis = current[i].localAxis * masterAxis;
368 			} else {
369 				current[i].axis = current[i].localAxis;
370 			}
371 			if ( clipModels[i] ) {
372 				clipModels[i]->Link( gameLocal.clip, self, i, current[i].origin, current[i].axis );
373 			}
374 		}
375 
376 		// FIXME: return false if master did not move
377 		return true;
378 	}
379 	return false;
380 }
381 
382 /*
383 ================
384 idPhysics_StaticMulti::UpdateTime
385 ================
386 */
UpdateTime(int endTimeMSec)387 void idPhysics_StaticMulti::UpdateTime( int endTimeMSec ) {
388 }
389 
390 /*
391 ================
392 idPhysics_StaticMulti::GetTime
393 ================
394 */
GetTime(void) const395 int idPhysics_StaticMulti::GetTime( void ) const {
396 	return 0;
397 }
398 
399 /*
400 ================
401 idPhysics_StaticMulti::GetImpactInfo
402 ================
403 */
GetImpactInfo(const int id,const idVec3 & point,impactInfo_t * info) const404 void idPhysics_StaticMulti::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
405 	memset( info, 0, sizeof( *info ) );
406 }
407 
408 /*
409 ================
410 idPhysics_StaticMulti::ApplyImpulse
411 ================
412 */
ApplyImpulse(const int id,const idVec3 & point,const idVec3 & impulse)413 void idPhysics_StaticMulti::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
414 }
415 
416 /*
417 ================
418 idPhysics_StaticMulti::AddForce
419 ================
420 */
AddForce(const int id,const idVec3 & point,const idVec3 & force)421 void idPhysics_StaticMulti::AddForce( const int id, const idVec3 &point, const idVec3 &force ) {
422 }
423 
424 /*
425 ================
426 idPhysics_StaticMulti::Activate
427 ================
428 */
Activate(void)429 void idPhysics_StaticMulti::Activate( void ) {
430 }
431 
432 /*
433 ================
434 idPhysics_StaticMulti::PutToRest
435 ================
436 */
PutToRest(void)437 void idPhysics_StaticMulti::PutToRest( void ) {
438 }
439 
440 /*
441 ================
442 idPhysics_StaticMulti::IsAtRest
443 ================
444 */
IsAtRest(void) const445 bool idPhysics_StaticMulti::IsAtRest( void ) const {
446 	return true;
447 }
448 
449 /*
450 ================
451 idPhysics_StaticMulti::GetRestStartTime
452 ================
453 */
GetRestStartTime(void) const454 int idPhysics_StaticMulti::GetRestStartTime( void ) const {
455 	return 0;
456 }
457 
458 /*
459 ================
460 idPhysics_StaticMulti::IsPushable
461 ================
462 */
IsPushable(void) const463 bool idPhysics_StaticMulti::IsPushable( void ) const {
464 	return false;
465 }
466 
467 /*
468 ================
469 idPhysics_StaticMulti::SaveState
470 ================
471 */
SaveState(void)472 void idPhysics_StaticMulti::SaveState( void ) {
473 }
474 
475 /*
476 ================
477 idPhysics_StaticMulti::RestoreState
478 ================
479 */
RestoreState(void)480 void idPhysics_StaticMulti::RestoreState( void ) {
481 }
482 
483 /*
484 ================
485 idPhysics_StaticMulti::SetOrigin
486 ================
487 */
SetOrigin(const idVec3 & newOrigin,int id)488 void idPhysics_StaticMulti::SetOrigin( const idVec3 &newOrigin, int id ) {
489 	idVec3 masterOrigin;
490 	idMat3 masterAxis;
491 
492 	if ( id >= 0 && id < clipModels.Num() ) {
493 		current[id].localOrigin = newOrigin;
494 		if ( hasMaster ) {
495 			self->GetMasterPosition( masterOrigin, masterAxis );
496 			current[id].origin = masterOrigin + newOrigin * masterAxis;
497 		} else {
498 			current[id].origin = newOrigin;
499 		}
500 		if ( clipModels[id] ) {
501 			clipModels[id]->Link( gameLocal.clip, self, id, current[id].origin, current[id].axis );
502 		}
503 	} else if ( id == -1 ) {
504 		if ( hasMaster ) {
505 			self->GetMasterPosition( masterOrigin, masterAxis );
506 			Translate( masterOrigin + masterAxis * newOrigin - current[0].origin );
507 		} else {
508 			Translate( newOrigin - current[0].origin );
509 		}
510 	}
511 }
512 
513 /*
514 ================
515 idPhysics_StaticMulti::SetAxis
516 ================
517 */
SetAxis(const idMat3 & newAxis,int id)518 void idPhysics_StaticMulti::SetAxis( const idMat3 &newAxis, int id ) {
519 	idVec3 masterOrigin;
520 	idMat3 masterAxis;
521 
522 	if ( id >= 0 && id < clipModels.Num() ) {
523 		current[id].localAxis = newAxis;
524 		if ( hasMaster && isOrientated ) {
525 			self->GetMasterPosition( masterOrigin, masterAxis );
526 			current[id].axis = newAxis * masterAxis;
527 		} else {
528 			current[id].axis = newAxis;
529 		}
530 		if ( clipModels[id] ) {
531 			clipModels[id]->Link( gameLocal.clip, self, id, current[id].origin, current[id].axis );
532 		}
533 	} else if ( id == -1 ) {
534 		idMat3 axis;
535 		idRotation rotation;
536 
537 		if ( hasMaster ) {
538 			self->GetMasterPosition( masterOrigin, masterAxis );
539 			axis = current[0].axis.Transpose() * ( newAxis * masterAxis );
540 		} else {
541 			axis = current[0].axis.Transpose() * newAxis;
542 		}
543 		rotation = axis.ToRotation();
544 		rotation.SetOrigin( current[0].origin );
545 
546 		Rotate( rotation );
547 	}
548 }
549 
550 /*
551 ================
552 idPhysics_StaticMulti::Translate
553 ================
554 */
Translate(const idVec3 & translation,int id)555 void idPhysics_StaticMulti::Translate( const idVec3 &translation, int id ) {
556 	int i;
557 
558 	if ( id >= 0 && id < clipModels.Num() ) {
559 		current[id].localOrigin += translation;
560 		current[id].origin += translation;
561 
562 		if ( clipModels[id] ) {
563 			clipModels[id]->Link( gameLocal.clip, self, id, current[id].origin, current[id].axis );
564 		}
565 	} else if ( id == -1 ) {
566 		for ( i = 0; i < clipModels.Num(); i++ ) {
567 			current[i].localOrigin += translation;
568 			current[i].origin += translation;
569 
570 			if ( clipModels[i] ) {
571 				clipModels[i]->Link( gameLocal.clip, self, i, current[i].origin, current[i].axis );
572 			}
573 		}
574 	}
575 }
576 
577 /*
578 ================
579 idPhysics_StaticMulti::Rotate
580 ================
581 */
Rotate(const idRotation & rotation,int id)582 void idPhysics_StaticMulti::Rotate( const idRotation &rotation, int id ) {
583 	int i;
584 	idVec3 masterOrigin;
585 	idMat3 masterAxis;
586 
587 	if ( id >= 0 && id < clipModels.Num() ) {
588 		current[id].origin *= rotation;
589 		current[id].axis *= rotation.ToMat3();
590 
591 		if ( hasMaster ) {
592 			self->GetMasterPosition( masterOrigin, masterAxis );
593 			current[id].localAxis *= rotation.ToMat3();
594 			current[id].localOrigin = ( current[id].origin - masterOrigin ) * masterAxis.Transpose();
595 		} else {
596 			current[id].localAxis = current[id].axis;
597 			current[id].localOrigin = current[id].origin;
598 		}
599 
600 		if ( clipModels[id] ) {
601 			clipModels[id]->Link( gameLocal.clip, self, id, current[id].origin, current[id].axis );
602 		}
603 	} else if ( id == -1 ) {
604 		for ( i = 0; i < clipModels.Num(); i++ ) {
605 			current[i].origin *= rotation;
606 			current[i].axis *= rotation.ToMat3();
607 
608 			if ( hasMaster ) {
609 				self->GetMasterPosition( masterOrigin, masterAxis );
610 				current[i].localAxis *= rotation.ToMat3();
611 				current[i].localOrigin = ( current[i].origin - masterOrigin ) * masterAxis.Transpose();
612 			} else {
613 				current[i].localAxis = current[i].axis;
614 				current[i].localOrigin = current[i].origin;
615 			}
616 
617 			if ( clipModels[i] ) {
618 				clipModels[i]->Link( gameLocal.clip, self, i, current[i].origin, current[i].axis );
619 			}
620 		}
621 	}
622 }
623 
624 /*
625 ================
626 idPhysics_StaticMulti::GetOrigin
627 ================
628 */
GetOrigin(int id) const629 const idVec3 &idPhysics_StaticMulti::GetOrigin( int id ) const {
630 	if ( id >= 0 && id < clipModels.Num() ) {
631 		return current[id].origin;
632 	}
633 	if ( clipModels.Num() ) {
634 		return current[0].origin;
635 	} else {
636 		return vec3_origin;
637 	}
638 }
639 
640 /*
641 ================
642 idPhysics_StaticMulti::GetAxis
643 ================
644 */
GetAxis(int id) const645 const idMat3 &idPhysics_StaticMulti::GetAxis( int id ) const {
646 	if ( id >= 0 && id < clipModels.Num() ) {
647 		return current[id].axis;
648 	}
649 	if ( clipModels.Num() ) {
650 		return current[0].axis;
651 	} else {
652 		return mat3_identity;
653 	}
654 }
655 
656 /*
657 ================
658 idPhysics_StaticMulti::SetLinearVelocity
659 ================
660 */
SetLinearVelocity(const idVec3 & newLinearVelocity,int id)661 void idPhysics_StaticMulti::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
662 }
663 
664 /*
665 ================
666 idPhysics_StaticMulti::SetAngularVelocity
667 ================
668 */
SetAngularVelocity(const idVec3 & newAngularVelocity,int id)669 void idPhysics_StaticMulti::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
670 }
671 
672 /*
673 ================
674 idPhysics_StaticMulti::GetLinearVelocity
675 ================
676 */
GetLinearVelocity(int id) const677 const idVec3 &idPhysics_StaticMulti::GetLinearVelocity( int id ) const {
678 	return vec3_origin;
679 }
680 
681 /*
682 ================
683 idPhysics_StaticMulti::GetAngularVelocity
684 ================
685 */
GetAngularVelocity(int id) const686 const idVec3 &idPhysics_StaticMulti::GetAngularVelocity( int id ) const {
687 	return vec3_origin;
688 }
689 
690 /*
691 ================
692 idPhysics_StaticMulti::SetGravity
693 ================
694 */
SetGravity(const idVec3 & newGravity)695 void idPhysics_StaticMulti::SetGravity( const idVec3 &newGravity ) {
696 }
697 
698 /*
699 ================
700 idPhysics_StaticMulti::GetGravity
701 ================
702 */
GetGravity(void) const703 const idVec3 &idPhysics_StaticMulti::GetGravity( void ) const {
704 	static idVec3 gravity( 0, 0, -g_gravity.GetFloat() );
705 	return gravity;
706 }
707 
708 /*
709 ================
710 idPhysics_StaticMulti::GetGravityNormal
711 ================
712 */
GetGravityNormal(void) const713 const idVec3 &idPhysics_StaticMulti::GetGravityNormal( void ) const {
714 	static idVec3 gravity( 0, 0, -1 );
715 	return gravity;
716 }
717 
718 /*
719 ================
720 idPhysics_StaticMulti::ClipTranslation
721 ================
722 */
ClipTranslation(trace_t & results,const idVec3 & translation,const idClipModel * model) const723 void idPhysics_StaticMulti::ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const {
724 	memset( &results, 0, sizeof( trace_t ) );
725 	gameLocal.Warning( "idPhysics_StaticMulti::ClipTranslation called" );
726 }
727 
728 /*
729 ================
730 idPhysics_StaticMulti::ClipRotation
731 ================
732 */
ClipRotation(trace_t & results,const idRotation & rotation,const idClipModel * model) const733 void idPhysics_StaticMulti::ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const {
734 	memset( &results, 0, sizeof( trace_t ) );
735 	gameLocal.Warning( "idPhysics_StaticMulti::ClipRotation called" );
736 }
737 
738 /*
739 ================
740 idPhysics_StaticMulti::ClipContents
741 ================
742 */
ClipContents(const idClipModel * model) const743 int idPhysics_StaticMulti::ClipContents( const idClipModel *model ) const {
744 	int i, contents;
745 
746 	contents = 0;
747 	for ( i = 0; i < clipModels.Num(); i++ ) {
748 		if ( clipModels[i] ) {
749 			if ( model ) {
750 				contents |= gameLocal.clip.ContentsModel( clipModels[i]->GetOrigin(), clipModels[i], clipModels[i]->GetAxis(), -1,
751 											model->Handle(), model->GetOrigin(), model->GetAxis() );
752 			} else {
753 				contents |= gameLocal.clip.Contents( clipModels[i]->GetOrigin(), clipModels[i], clipModels[i]->GetAxis(), -1, NULL );
754 			}
755 		}
756 	}
757 	return contents;
758 }
759 
760 /*
761 ================
762 idPhysics_StaticMulti::DisableClip
763 ================
764 */
DisableClip(void)765 void idPhysics_StaticMulti::DisableClip( void ) {
766 	int i;
767 
768 	for ( i = 0; i < clipModels.Num(); i++ ) {
769 		if ( clipModels[i] ) {
770 			clipModels[i]->Disable();
771 		}
772 	}
773 }
774 
775 /*
776 ================
777 idPhysics_StaticMulti::EnableClip
778 ================
779 */
EnableClip(void)780 void idPhysics_StaticMulti::EnableClip( void ) {
781 	int i;
782 
783 	for ( i = 0; i < clipModels.Num(); i++ ) {
784 		if ( clipModels[i] ) {
785 			clipModels[i]->Enable();
786 		}
787 	}
788 }
789 
790 /*
791 ================
792 idPhysics_StaticMulti::UnlinkClip
793 ================
794 */
UnlinkClip(void)795 void idPhysics_StaticMulti::UnlinkClip( void ) {
796 	int i;
797 
798 	for ( i = 0; i < clipModels.Num(); i++ ) {
799 		if ( clipModels[i] ) {
800 			clipModels[i]->Unlink();
801 		}
802 	}
803 }
804 
805 /*
806 ================
807 idPhysics_StaticMulti::LinkClip
808 ================
809 */
LinkClip(void)810 void idPhysics_StaticMulti::LinkClip( void ) {
811 	int i;
812 
813 	for ( i = 0; i < clipModels.Num(); i++ ) {
814 		if ( clipModels[i] ) {
815 			clipModels[i]->Link( gameLocal.clip, self, i, current[i].origin, current[i].axis );
816 		}
817 	}
818 }
819 
820 /*
821 ================
822 idPhysics_StaticMulti::EvaluateContacts
823 ================
824 */
EvaluateContacts(void)825 bool idPhysics_StaticMulti::EvaluateContacts( void ) {
826 	return false;
827 }
828 
829 /*
830 ================
831 idPhysics_StaticMulti::GetNumContacts
832 ================
833 */
GetNumContacts(void) const834 int idPhysics_StaticMulti::GetNumContacts( void ) const {
835 	return 0;
836 }
837 
838 /*
839 ================
840 idPhysics_StaticMulti::GetContact
841 ================
842 */
GetContact(int num) const843 const contactInfo_t &idPhysics_StaticMulti::GetContact( int num ) const {
844 	static contactInfo_t info;
845 	memset( &info, 0, sizeof( info ) );
846 	return info;
847 }
848 
849 /*
850 ================
851 idPhysics_StaticMulti::ClearContacts
852 ================
853 */
ClearContacts(void)854 void idPhysics_StaticMulti::ClearContacts( void ) {
855 }
856 
857 /*
858 ================
859 idPhysics_StaticMulti::AddContactEntity
860 ================
861 */
AddContactEntity(idEntity * e)862 void idPhysics_StaticMulti::AddContactEntity( idEntity *e ) {
863 }
864 
865 /*
866 ================
867 idPhysics_StaticMulti::RemoveContactEntity
868 ================
869 */
RemoveContactEntity(idEntity * e)870 void idPhysics_StaticMulti::RemoveContactEntity( idEntity *e ) {
871 }
872 
873 /*
874 ================
875 idPhysics_StaticMulti::HasGroundContacts
876 ================
877 */
HasGroundContacts(void) const878 bool idPhysics_StaticMulti::HasGroundContacts( void ) const {
879 	return false;
880 }
881 
882 /*
883 ================
884 idPhysics_StaticMulti::IsGroundEntity
885 ================
886 */
IsGroundEntity(int entityNum) const887 bool idPhysics_StaticMulti::IsGroundEntity( int entityNum ) const {
888 	return false;
889 }
890 
891 /*
892 ================
893 idPhysics_StaticMulti::IsGroundClipModel
894 ================
895 */
IsGroundClipModel(int entityNum,int id) const896 bool idPhysics_StaticMulti::IsGroundClipModel( int entityNum, int id ) const {
897 	return false;
898 }
899 
900 /*
901 ================
902 idPhysics_StaticMulti::SetPushed
903 ================
904 */
SetPushed(int deltaTime)905 void idPhysics_StaticMulti::SetPushed( int deltaTime ) {
906 }
907 
908 /*
909 ================
910 idPhysics_StaticMulti::GetPushedLinearVelocity
911 ================
912 */
GetPushedLinearVelocity(const int id) const913 const idVec3 &idPhysics_StaticMulti::GetPushedLinearVelocity( const int id ) const {
914 	return vec3_origin;
915 }
916 
917 /*
918 ================
919 idPhysics_StaticMulti::GetPushedAngularVelocity
920 ================
921 */
GetPushedAngularVelocity(const int id) const922 const idVec3 &idPhysics_StaticMulti::GetPushedAngularVelocity( const int id ) const {
923 	return vec3_origin;
924 }
925 
926 /*
927 ================
928 idPhysics_StaticMulti::SetMaster
929 ================
930 */
SetMaster(idEntity * master,const bool orientated)931 void idPhysics_StaticMulti::SetMaster( idEntity *master, const bool orientated ) {
932 	int i;
933 	idVec3 masterOrigin;
934 	idMat3 masterAxis;
935 
936 	if ( master ) {
937 		if ( !hasMaster ) {
938 			// transform from world space to master space
939 			self->GetMasterPosition( masterOrigin, masterAxis );
940 			for ( i = 0; i < clipModels.Num(); i++ ) {
941 				current[i].localOrigin = ( current[i].origin - masterOrigin ) * masterAxis.Transpose();
942 				if ( orientated ) {
943 					current[i].localAxis = current[i].axis * masterAxis.Transpose();
944 				} else {
945 					current[i].localAxis = current[i].axis;
946 				}
947 			}
948 			hasMaster = true;
949 			isOrientated = orientated;
950 		}
951 	} else {
952 		if ( hasMaster ) {
953 			hasMaster = false;
954 		}
955 	}
956 }
957 
958 /*
959 ================
960 idPhysics_StaticMulti::GetBlockingInfo
961 ================
962 */
GetBlockingInfo(void) const963 const trace_t *idPhysics_StaticMulti::GetBlockingInfo( void ) const {
964 	return NULL;
965 }
966 
967 /*
968 ================
969 idPhysics_StaticMulti::GetBlockingEntity
970 ================
971 */
GetBlockingEntity(void) const972 idEntity *idPhysics_StaticMulti::GetBlockingEntity( void ) const {
973 	return NULL;
974 }
975 
976 /*
977 ================
978 idPhysics_StaticMulti::GetLinearEndTime
979 ================
980 */
GetLinearEndTime(void) const981 int idPhysics_StaticMulti::GetLinearEndTime( void ) const {
982 	return 0;
983 }
984 
985 /*
986 ================
987 idPhysics_StaticMulti::GetAngularEndTime
988 ================
989 */
GetAngularEndTime(void) const990 int idPhysics_StaticMulti::GetAngularEndTime( void ) const {
991 	return 0;
992 }
993 
994 /*
995 ================
996 idPhysics_StaticMulti::WriteToSnapshot
997 ================
998 */
WriteToSnapshot(idBitMsgDelta & msg) const999 void idPhysics_StaticMulti::WriteToSnapshot( idBitMsgDelta &msg ) const {
1000 	int i;
1001 	idCQuat quat, localQuat;
1002 
1003 	msg.WriteByte( current.Num() );
1004 
1005 	for ( i = 0; i < current.Num(); i++ ) {
1006 		quat = current[i].axis.ToCQuat();
1007 		localQuat = current[i].localAxis.ToCQuat();
1008 
1009 		msg.WriteFloat( current[i].origin[0] );
1010 		msg.WriteFloat( current[i].origin[1] );
1011 		msg.WriteFloat( current[i].origin[2] );
1012 		msg.WriteFloat( quat.x );
1013 		msg.WriteFloat( quat.y );
1014 		msg.WriteFloat( quat.z );
1015 		msg.WriteDeltaFloat( current[i].origin[0], current[i].localOrigin[0] );
1016 		msg.WriteDeltaFloat( current[i].origin[1], current[i].localOrigin[1] );
1017 		msg.WriteDeltaFloat( current[i].origin[2], current[i].localOrigin[2] );
1018 		msg.WriteDeltaFloat( quat.x, localQuat.x );
1019 		msg.WriteDeltaFloat( quat.y, localQuat.y );
1020 		msg.WriteDeltaFloat( quat.z, localQuat.z );
1021 	}
1022 }
1023 
1024 /*
1025 ================
1026 idPhysics_StaticMulti::ReadFromSnapshot
1027 ================
1028 */
ReadFromSnapshot(const idBitMsgDelta & msg)1029 void idPhysics_StaticMulti::ReadFromSnapshot( const idBitMsgDelta &msg ) {
1030 	int i, num id_attribute((unused));
1031 	idCQuat quat, localQuat;
1032 
1033 	num = msg.ReadByte();
1034 	assert( num == current.Num() );
1035 
1036 	for ( i = 0; i < current.Num(); i++ ) {
1037 		current[i].origin[0] = msg.ReadFloat();
1038 		current[i].origin[1] = msg.ReadFloat();
1039 		current[i].origin[2] = msg.ReadFloat();
1040 		quat.x = msg.ReadFloat();
1041 		quat.y = msg.ReadFloat();
1042 		quat.z = msg.ReadFloat();
1043 		current[i].localOrigin[0] = msg.ReadDeltaFloat( current[i].origin[0] );
1044 		current[i].localOrigin[1] = msg.ReadDeltaFloat( current[i].origin[1] );
1045 		current[i].localOrigin[2] = msg.ReadDeltaFloat( current[i].origin[2] );
1046 		localQuat.x = msg.ReadDeltaFloat( quat.x );
1047 		localQuat.y = msg.ReadDeltaFloat( quat.y );
1048 		localQuat.z = msg.ReadDeltaFloat( quat.z );
1049 
1050 		current[i].axis = quat.ToMat3();
1051 		current[i].localAxis = localQuat.ToMat3();
1052 	}
1053 }
1054