doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BrittleFracture.cpp
Go to the documentation of this file.
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 "../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "Game_local.h"
33 
34 
36  EVENT( EV_Activate, idBrittleFracture::Event_Activate )
37  EVENT( EV_Touch, idBrittleFracture::Event_Touch )
39 
42 
43 static const char *brittleFracture_SnapshotName = "_BrittleFracture_Snapshot_";
44 
45 /*
46 ================
47 idBrittleFracture::idBrittleFracture
48 ================
49 */
51  material = NULL;
52  decalMaterial = NULL;
53  decalSize = 0.0f;
54  maxShardArea = 0.0f;
55  maxShatterRadius = 0.0f;
56  minShatterRadius = 0.0f;
57  linearVelocityScale = 0.0f;
58  angularVelocityScale = 0.0f;
59  shardMass = 0.0f;
60  density = 0.0f;
61  friction = 0.0f;
62  bouncyness = 0.0f;
63  fxFracture.Clear();
64 
65  bounds.Clear();
66  disableFracture = false;
67 
68  lastRenderEntityUpdate = -1;
69  changed = false;
70 
71  fl.networkSync = true;
72 
73 #ifdef _D3XP
74  isXraySurface = false;
75 #endif
76 }
77 
78 /*
79 ================
80 idBrittleFracture::~idBrittleFracture
81 ================
82 */
84  int i;
85 
86  for ( i = 0; i < shards.Num(); i++ ) {
87  shards[i]->decals.DeleteContents( true );
88  delete shards[i];
89  }
90 
91  // make sure the render entity is freed before the model is freed
92  FreeModelDef();
94 }
95 
96 /*
97 ================
98 idBrittleFracture::Save
99 ================
100 */
101 void idBrittleFracture::Save( idSaveGame *savefile ) const {
102  int i, j;
103 
104  savefile->WriteInt( health );
105  entityFlags_s flags = fl;
106  LittleBitField( &flags, sizeof( flags ) );
107  savefile->Write( &flags, sizeof( flags ) );
108 
109  // setttings
110  savefile->WriteMaterial( material );
111  savefile->WriteMaterial( decalMaterial );
112  savefile->WriteFloat( decalSize );
113  savefile->WriteFloat( maxShardArea );
114  savefile->WriteFloat( maxShatterRadius );
115  savefile->WriteFloat( minShatterRadius );
116  savefile->WriteFloat( linearVelocityScale );
117  savefile->WriteFloat( angularVelocityScale );
118  savefile->WriteFloat( shardMass );
119  savefile->WriteFloat( density );
120  savefile->WriteFloat( friction );
121  savefile->WriteFloat( bouncyness );
122  savefile->WriteString( fxFracture );
123 
124  // state
125  savefile->WriteBounds( bounds );
126  savefile->WriteBool( disableFracture );
127 
128  savefile->WriteInt( lastRenderEntityUpdate );
129  savefile->WriteBool( changed );
130 
131  savefile->WriteStaticObject( physicsObj );
132 
133  savefile->WriteInt( shards.Num() );
134  for ( i = 0; i < shards.Num(); i++ ) {
135  savefile->WriteWinding( shards[i]->winding );
136 
137  savefile->WriteInt( shards[i]->decals.Num() );
138  for ( j = 0; j < shards[i]->decals.Num(); j++ ) {
139  savefile->WriteWinding( *shards[i]->decals[j] );
140  }
141 
142  savefile->WriteInt( shards[i]->neighbours.Num() );
143  for ( j = 0; j < shards[i]->neighbours.Num(); j++ ) {
144  int index = shards.FindIndex(shards[i]->neighbours[j]);
145  assert(index != -1);
146  savefile->WriteInt( index );
147  }
148 
149  savefile->WriteInt( shards[i]->edgeHasNeighbour.Num() );
150  for ( j = 0; j < shards[i]->edgeHasNeighbour.Num(); j++ ) {
151  savefile->WriteBool( shards[i]->edgeHasNeighbour[j] );
152  }
153 
154  savefile->WriteInt( shards[i]->droppedTime );
155  savefile->WriteInt( shards[i]->islandNum );
156  savefile->WriteBool( shards[i]->atEdge );
157  savefile->WriteStaticObject( shards[i]->physicsObj );
158  }
159 
160 #ifdef _D3XP
161  savefile->WriteBool( isXraySurface );
162 #endif
163 }
164 
165 /*
166 ================
167 idBrittleFracture::Restore
168 ================
169 */
171  int i, j , num;
172 
174  renderEntity.hModel->InitEmpty( brittleFracture_SnapshotName );
176  renderEntity.noShadow = true;
177  renderEntity.noSelfShadow = true;
179 
180  savefile->ReadInt( health );
181  savefile->Read( &fl, sizeof( fl ) );
182  LittleBitField( &fl, sizeof( fl ) );
183 
184  // setttings
185  savefile->ReadMaterial( material );
186  savefile->ReadMaterial( decalMaterial );
187  savefile->ReadFloat( decalSize );
188  savefile->ReadFloat( maxShardArea );
189  savefile->ReadFloat( maxShatterRadius );
190  savefile->ReadFloat( minShatterRadius );
191  savefile->ReadFloat( linearVelocityScale );
192  savefile->ReadFloat( angularVelocityScale );
193  savefile->ReadFloat( shardMass );
194  savefile->ReadFloat( density );
195  savefile->ReadFloat( friction );
196  savefile->ReadFloat( bouncyness );
197  savefile->ReadString( fxFracture );
198 
199  // state
200  savefile->ReadBounds(bounds);
201  savefile->ReadBool( disableFracture );
202 
203  savefile->ReadInt( lastRenderEntityUpdate );
204  savefile->ReadBool( changed );
205 
206  savefile->ReadStaticObject( physicsObj );
208 
209  savefile->ReadInt( num );
210  shards.SetNum( num );
211  for ( i = 0; i < num; i++ ) {
212  shards[i] = new shard_t;
213  }
214 
215  for ( i = 0; i < num; i++ ) {
216  savefile->ReadWinding( shards[i]->winding );
217 
218  savefile->ReadInt( j );
219  shards[i]->decals.SetNum( j );
220  for ( j = 0; j < shards[i]->decals.Num(); j++ ) {
221  shards[i]->decals[j] = new idFixedWinding;
222  savefile->ReadWinding( *shards[i]->decals[j] );
223  }
224 
225  savefile->ReadInt( j );
226  shards[i]->neighbours.SetNum( j );
227  for ( j = 0; j < shards[i]->neighbours.Num(); j++ ) {
228  int index;
229  savefile->ReadInt( index );
230  assert(index != -1);
231  shards[i]->neighbours[j] = shards[index];
232  }
233 
234  savefile->ReadInt( j );
235  shards[i]->edgeHasNeighbour.SetNum( j );
236  for ( j = 0; j < shards[i]->edgeHasNeighbour.Num(); j++ ) {
237  savefile->ReadBool( shards[i]->edgeHasNeighbour[j] );
238  }
239 
240  savefile->ReadInt( shards[i]->droppedTime );
241  savefile->ReadInt( shards[i]->islandNum );
242  savefile->ReadBool( shards[i]->atEdge );
243  savefile->ReadStaticObject( shards[i]->physicsObj );
244  if ( shards[i]->droppedTime < 0 ) {
245  shards[i]->clipModel = physicsObj.GetClipModel( i );
246  } else {
247  shards[i]->clipModel = shards[i]->physicsObj.GetClipModel();
248  }
249  }
250 
251 #ifdef _D3XP
252  savefile->ReadBool( isXraySurface );
253 #endif
254 }
255 
256 /*
257 ================
258 idBrittleFracture::Spawn
259 ================
260 */
262 
263  // get shard properties
265  decalSize = spawnArgs.GetFloat( "decalSize", "40" );
266  maxShardArea = spawnArgs.GetFloat( "maxShardArea", "200" );
268  maxShatterRadius = spawnArgs.GetFloat( "maxShatterRadius", "40" );
269  minShatterRadius = spawnArgs.GetFloat( "minShatterRadius", "10" );
270  linearVelocityScale = spawnArgs.GetFloat( "linearVelocityScale", "0.1" );
271  angularVelocityScale = spawnArgs.GetFloat( "angularVelocityScale", "40" );
272  fxFracture = spawnArgs.GetString( "fx" );
273 
274  // get rigid body properties
275  shardMass = spawnArgs.GetFloat( "shardMass", "20" );
276  shardMass = idMath::ClampFloat( 0.001f, 1000.0f, shardMass );
277  spawnArgs.GetFloat( "density", "0.1", density );
278  density = idMath::ClampFloat( 0.001f, 1000.0f, density );
279  spawnArgs.GetFloat( "friction", "0.4", friction );
280  friction = idMath::ClampFloat( 0.0f, 1.0f, friction );
281  spawnArgs.GetFloat( "bouncyness", "0.01", bouncyness );
283 
284  disableFracture = spawnArgs.GetBool( "disableFracture", "0" );
285  health = spawnArgs.GetInt( "health", "40" );
286  fl.takedamage = true;
287 
288  // FIXME: set "bleed" so idProjectile calls AddDamageEffect
289  spawnArgs.SetBool( "bleed", 1 );
290 
291 #ifdef _D3XP
292  // check for xray surface
293  if ( 1 ) {
294  const idRenderModel *model = renderEntity.hModel;
295 
296  isXraySurface = false;
297 
298  for ( int i = 0; i < model->NumSurfaces(); i++ ) {
299  const modelSurface_t *surf = model->Surface( i );
300 
301  if ( idStr( surf->shader->GetName() ) == "textures/smf/window_scratch" ) {
302  isXraySurface = true;
303  break;
304  }
305  }
306  }
307 #endif
308 
310 
311  FindNeighbours();
312 
314  renderEntity.hModel->InitEmpty( brittleFracture_SnapshotName );
316  renderEntity.noShadow = true;
317  renderEntity.noSelfShadow = true;
319 }
320 
321 /*
322 ================
323 idBrittleFracture::AddShard
324 ================
325 */
327  shard_t *shard = new shard_t;
328  shard->clipModel = clipModel;
329  shard->droppedTime = -1;
330  shard->winding = w;
331  shard->decals.Clear();
332  shard->edgeHasNeighbour.AssureSize( w.GetNumPoints(), false );
333  shard->neighbours.Clear();
334  shard->atEdge = false;
335  shards.Append( shard );
336 }
337 
338 /*
339 ================
340 idBrittleFracture::RemoveShard
341 ================
342 */
344  int i;
345 
346  delete shards[index];
347  shards.RemoveIndex( index );
348  physicsObj.RemoveIndex( index );
349 
350  for ( i = index; i < shards.Num(); i++ ) {
351  shards[i]->clipModel->SetId( i );
352  }
353 }
354 
355 /*
356 ================
357 idBrittleFracture::UpdateRenderEntity
358 ================
359 */
360 bool idBrittleFracture::UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) const {
361  int i, j, k, n, msec, numTris, numDecalTris;
362  float fade;
363  dword packedColor;
364  srfTriangles_t *tris, *decalTris;
365  modelSurface_t surface;
366  idDrawVert *v;
367  idPlane plane;
368  idMat3 tangents;
369 
370  // this may be triggered by a model trace or other non-view related source,
371  // to which we should look like an empty model
372  if ( !renderView ) {
373  return false;
374  }
375 
376  // don't regenerate it if it is current
378  return false;
379  }
380 
382  changed = false;
383 
384  numTris = 0;
385  numDecalTris = 0;
386  for ( i = 0; i < shards.Num(); i++ ) {
387  n = shards[i]->winding.GetNumPoints();
388  if ( n > 2 ) {
389  numTris += n - 2;
390  }
391  for ( k = 0; k < shards[i]->decals.Num(); k++ ) {
392  n = shards[i]->decals[k]->GetNumPoints();
393  if ( n > 2 ) {
394  numDecalTris += n - 2;
395  }
396  }
397  }
398 
399  // FIXME: re-use model surfaces
400  renderEntity->hModel->InitEmpty( brittleFracture_SnapshotName );
401 
402  // allocate triangle surfaces for the fractures and decals
403  tris = renderEntity->hModel->AllocSurfaceTriangles( numTris * 3, material->ShouldCreateBackSides() ? numTris * 6 : numTris * 3 );
404  decalTris = renderEntity->hModel->AllocSurfaceTriangles( numDecalTris * 3, decalMaterial->ShouldCreateBackSides() ? numDecalTris * 6 : numDecalTris * 3 );
405 
406  for ( i = 0; i < shards.Num(); i++ ) {
407  const idVec3 &origin = shards[i]->clipModel->GetOrigin();
408  const idMat3 &axis = shards[i]->clipModel->GetAxis();
409 
410  fade = 1.0f;
411  if ( shards[i]->droppedTime >= 0 ) {
412  msec = gameLocal.time - shards[i]->droppedTime - SHARD_FADE_START;
413  if ( msec > 0 ) {
414  fade = 1.0f - (float) msec / ( SHARD_ALIVE_TIME - SHARD_FADE_START );
415  }
416  }
417  packedColor = PackColor( idVec4( renderEntity->shaderParms[ SHADERPARM_RED ] * fade,
418  renderEntity->shaderParms[ SHADERPARM_GREEN ] * fade,
419  renderEntity->shaderParms[ SHADERPARM_BLUE ] * fade,
420  fade ) );
421 
422  const idWinding &winding = shards[i]->winding;
423 
424  winding.GetPlane( plane );
425  tangents = ( plane.Normal() * axis ).ToMat3();
426 
427  for ( j = 2; j < winding.GetNumPoints(); j++ ) {
428 
429  v = &tris->verts[tris->numVerts++];
430  v->Clear();
431  v->xyz = origin + winding[0].ToVec3() * axis;
432  v->st[0] = winding[0].s;
433  v->st[1] = winding[0].t;
434  v->normal = tangents[0];
435  v->tangents[0] = tangents[1];
436  v->tangents[1] = tangents[2];
437  v->SetColor( packedColor );
438 
439  v = &tris->verts[tris->numVerts++];
440  v->Clear();
441  v->xyz = origin + winding[j-1].ToVec3() * axis;
442  v->st[0] = winding[j-1].s;
443  v->st[1] = winding[j-1].t;
444  v->normal = tangents[0];
445  v->tangents[0] = tangents[1];
446  v->tangents[1] = tangents[2];
447  v->SetColor( packedColor );
448 
449  v = &tris->verts[tris->numVerts++];
450  v->Clear();
451  v->xyz = origin + winding[j].ToVec3() * axis;
452  v->st[0] = winding[j].s;
453  v->st[1] = winding[j].t;
454  v->normal = tangents[0];
455  v->tangents[0] = tangents[1];
456  v->tangents[1] = tangents[2];
457  v->SetColor( packedColor );
458 
459  tris->indexes[tris->numIndexes++] = tris->numVerts - 3;
460  tris->indexes[tris->numIndexes++] = tris->numVerts - 2;
461  tris->indexes[tris->numIndexes++] = tris->numVerts - 1;
462 
463  if ( material->ShouldCreateBackSides() ) {
464 
465  tris->indexes[tris->numIndexes++] = tris->numVerts - 2;
466  tris->indexes[tris->numIndexes++] = tris->numVerts - 3;
467  tris->indexes[tris->numIndexes++] = tris->numVerts - 1;
468  }
469  }
470 
471  for ( k = 0; k < shards[i]->decals.Num(); k++ ) {
472  const idWinding &decalWinding = *shards[i]->decals[k];
473 
474  for ( j = 2; j < decalWinding.GetNumPoints(); j++ ) {
475 
476  v = &decalTris->verts[decalTris->numVerts++];
477  v->Clear();
478  v->xyz = origin + decalWinding[0].ToVec3() * axis;
479  v->st[0] = decalWinding[0].s;
480  v->st[1] = decalWinding[0].t;
481  v->normal = tangents[0];
482  v->tangents[0] = tangents[1];
483  v->tangents[1] = tangents[2];
484  v->SetColor( packedColor );
485 
486  v = &decalTris->verts[decalTris->numVerts++];
487  v->Clear();
488  v->xyz = origin + decalWinding[j-1].ToVec3() * axis;
489  v->st[0] = decalWinding[j-1].s;
490  v->st[1] = decalWinding[j-1].t;
491  v->normal = tangents[0];
492  v->tangents[0] = tangents[1];
493  v->tangents[1] = tangents[2];
494  v->SetColor( packedColor );
495 
496  v = &decalTris->verts[decalTris->numVerts++];
497  v->Clear();
498  v->xyz = origin + decalWinding[j].ToVec3() * axis;
499  v->st[0] = decalWinding[j].s;
500  v->st[1] = decalWinding[j].t;
501  v->normal = tangents[0];
502  v->tangents[0] = tangents[1];
503  v->tangents[1] = tangents[2];
504  v->SetColor( packedColor );
505 
506  decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 3;
507  decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 2;
508  decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 1;
509 
511 
512  decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 2;
513  decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 3;
514  decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 1;
515  }
516  }
517  }
518  }
519 
520  tris->tangentsCalculated = true;
521  decalTris->tangentsCalculated = true;
522 
523  SIMDProcessor->MinMax( tris->bounds[0], tris->bounds[1], tris->verts, tris->numVerts );
524  SIMDProcessor->MinMax( decalTris->bounds[0], decalTris->bounds[1], decalTris->verts, decalTris->numVerts );
525 
526  memset( &surface, 0, sizeof( surface ) );
527  surface.shader = material;
528  surface.id = 0;
529  surface.geometry = tris;
530  renderEntity->hModel->AddSurface( surface );
531 
532  memset( &surface, 0, sizeof( surface ) );
533  surface.shader = decalMaterial;
534  surface.id = 1;
535  surface.geometry = decalTris;
536  renderEntity->hModel->AddSurface( surface );
537 
538  return true;
539 }
540 
541 /*
542 ================
543 idBrittleFracture::ModelCallback
544 ================
545 */
546 bool idBrittleFracture::ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) {
547  const idBrittleFracture *ent;
548 
549  ent = static_cast<idBrittleFracture *>(gameLocal.entities[ renderEntity->entityNum ]);
550  if ( !ent ) {
551  gameLocal.Error( "idBrittleFracture::ModelCallback: callback with NULL game entity" );
552  }
553 
554  return ent->UpdateRenderEntity( renderEntity, renderView );
555 }
556 
557 /*
558 ================
559 idBrittleFracture::Present
560 ================
561 */
563 
564  // don't present to the renderer if the entity hasn't changed
565  if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
566  return;
567  }
568  BecomeInactive( TH_UPDATEVISUALS );
569 
573 
574  // force an update because the bounds/origin/axis may stay the same while the model changes
575  renderEntity.forceUpdate = true;
576 
577  // add to refresh list
578  if ( modelDefHandle == -1 ) {
580  } else {
582  }
583 
584  changed = true;
585 }
586 
587 /*
588 ================
589 idBrittleFracture::Think
590 ================
591 */
593  int i, startTime, endTime, droppedTime;
594  shard_t *shard;
595  bool atRest = true, fading = false;
596 
597  // remove overdue shards
598  for ( i = 0; i < shards.Num(); i++ ) {
599  droppedTime = shards[i]->droppedTime;
600  if ( droppedTime != -1 ) {
601  if ( gameLocal.time - droppedTime > SHARD_ALIVE_TIME ) {
602  RemoveShard( i );
603  i--;
604  }
605  fading = true;
606  }
607  }
608 
609  // remove the entity when nothing is visible
610  if ( !shards.Num() ) {
611  PostEventMS( &EV_Remove, 0 );
612  return;
613  }
614 
615  if ( thinkFlags & TH_PHYSICS ) {
616 
617  startTime = gameLocal.previousTime;
618  endTime = gameLocal.time;
619 
620  // run physics on shards
621  for ( i = 0; i < shards.Num(); i++ ) {
622  shard = shards[i];
623 
624  if ( shard->droppedTime == -1 ) {
625  continue;
626  }
627 
628  shard->physicsObj.Evaluate( endTime - startTime, endTime );
629 
630  if ( !shard->physicsObj.IsAtRest() ) {
631  atRest = false;
632  }
633  }
634 
635  if ( atRest ) {
636  BecomeInactive( TH_PHYSICS );
637  } else {
638  BecomeActive( TH_PHYSICS );
639  }
640  }
641 
642  if ( !atRest || bounds.IsCleared() ) {
643  bounds.Clear();
644  for ( i = 0; i < shards.Num(); i++ ) {
645  bounds.AddBounds( shards[i]->clipModel->GetAbsBounds() );
646  }
647  }
648 
649  if ( fading ) {
651  } else {
653  }
654 
655  RunPhysics();
656  Present();
657 }
658 
659 /*
660 ================
661 idBrittleFracture::ApplyImpulse
662 ================
663 */
664 void idBrittleFracture::ApplyImpulse( idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse ) {
665 
666  if ( id < 0 || id >= shards.Num() ) {
667  return;
668  }
669 
670  if ( shards[id]->droppedTime != -1 ) {
671  shards[id]->physicsObj.ApplyImpulse( 0, point, impulse );
672  } else if ( health <= 0 && !disableFracture ) {
673  Shatter( point, impulse, gameLocal.time );
674  }
675 }
676 
677 /*
678 ================
679 idBrittleFracture::AddForce
680 ================
681 */
682 void idBrittleFracture::AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force ) {
683 
684  if ( id < 0 || id >= shards.Num() ) {
685  return;
686  }
687 
688  if ( shards[id]->droppedTime != -1 ) {
689  shards[id]->physicsObj.AddForce( 0, point, force );
690  } else if ( health <= 0 && !disableFracture ) {
691  Shatter( point, force, gameLocal.time );
692  }
693 }
694 
695 /*
696 ================
697 idBrittleFracture::ProjectDecal
698 ================
699 */
700 void idBrittleFracture::ProjectDecal( const idVec3 &point, const idVec3 &dir, const int time, const char *damageDefName ) {
701  int i, j, bits, clipBits;
702  float a, c, s;
704  idVec3 origin;
705  idMat3 axis, axistemp;
706  idPlane textureAxis[2];
707 
708  if ( gameLocal.isServer ) {
709  idBitMsg msg;
710  byte msgBuf[MAX_EVENT_PARAM_SIZE];
711 
712  msg.Init( msgBuf, sizeof( msgBuf ) );
713  msg.BeginWriting();
714  msg.WriteFloat( point[0] );
715  msg.WriteFloat( point[1] );
716  msg.WriteFloat( point[2] );
717  msg.WriteFloat( dir[0] );
718  msg.WriteFloat( dir[1] );
719  msg.WriteFloat( dir[2] );
720  ServerSendEvent( EVENT_PROJECT_DECAL, &msg, true, -1 );
721  }
722 
723  if ( time >= gameLocal.time ) {
724  // try to get the sound from the damage def
725  const idDeclEntityDef *damageDef = NULL;
726  const idSoundShader *sndShader = NULL;
727  if ( damageDefName ) {
728  damageDef = gameLocal.FindEntityDef( damageDefName, false );
729  if ( damageDef ) {
730  sndShader = declManager->FindSound( damageDef->dict.GetString( "snd_shatter", "" ) );
731  }
732  }
733 
734  if ( sndShader ) {
735  StartSoundShader( sndShader, SND_CHANNEL_ANY, 0, false, NULL );
736  } else {
737  StartSound( "snd_bullethole", SND_CHANNEL_ANY, 0, false, NULL );
738  }
739  }
740 
742  c = cos( a );
743  s = -sin( a );
744 
745  axis[2] = -dir;
746  axis[2].Normalize();
747  axis[2].NormalVectors( axistemp[0], axistemp[1] );
748  axis[0] = axistemp[ 0 ] * c + axistemp[ 1 ] * s;
749  axis[1] = axistemp[ 0 ] * s + axistemp[ 1 ] * -c;
750 
751  textureAxis[0] = axis[0] * ( 1.0f / decalSize );
752  textureAxis[0][3] = -( point * textureAxis[0].Normal() ) + 0.5f;
753 
754  textureAxis[1] = axis[1] * ( 1.0f / decalSize );
755  textureAxis[1][3] = -( point * textureAxis[1].Normal() ) + 0.5f;
756 
757  for ( i = 0; i < shards.Num(); i++ ) {
758  idFixedWinding &winding = shards[i]->winding;
759  origin = shards[i]->clipModel->GetOrigin();
760  axis = shards[i]->clipModel->GetAxis();
761  float d0, d1;
762 
763  clipBits = -1;
764  for ( j = 0; j < winding.GetNumPoints(); j++ ) {
765  idVec3 p = origin + winding[j].ToVec3() * axis;
766 
767  st[j].x = d0 = textureAxis[0].Distance( p );
768  st[j].y = d1 = textureAxis[1].Distance( p );
769 
770  bits = FLOATSIGNBITSET( d0 );
771  d0 = 1.0f - d0;
772  bits |= FLOATSIGNBITSET( d1 ) << 2;
773  d1 = 1.0f - d1;
774  bits |= FLOATSIGNBITSET( d0 ) << 1;
775  bits |= FLOATSIGNBITSET( d1 ) << 3;
776 
777  clipBits &= bits;
778  }
779 
780  if ( clipBits ) {
781  continue;
782  }
783 
784  idFixedWinding *decal = new idFixedWinding;
785  shards[i]->decals.Append( decal );
786 
787  decal->SetNumPoints( winding.GetNumPoints() );
788  for ( j = 0; j < winding.GetNumPoints(); j++ ) {
789  (*decal)[j].ToVec3() = winding[j].ToVec3();
790  (*decal)[j].s = st[j].x;
791  (*decal)[j].t = st[j].y;
792  }
793  }
794 
796 }
797 
798 /*
799 ================
800 idBrittleFracture::DropShard
801 ================
802 */
803 void idBrittleFracture::DropShard( shard_t *shard, const idVec3 &point, const idVec3 &dir, const float impulse, const int time ) {
804  int i, j, clipModelId;
805  float dist, f;
806  idVec3 dir2, origin;
807  idMat3 axis;
808  shard_t *neighbour;
809 
810  // don't display decals on dropped shards
811  shard->decals.DeleteContents( true );
812 
813  // remove neighbour pointers of neighbours pointing to this shard
814  for ( i = 0; i < shard->neighbours.Num(); i++ ) {
815  neighbour = shard->neighbours[i];
816  for ( j = 0; j < neighbour->neighbours.Num(); j++ ) {
817  if ( neighbour->neighbours[j] == shard ) {
818  neighbour->neighbours.RemoveIndex( j );
819  break;
820  }
821  }
822  }
823 
824  // remove neighbour pointers
825  shard->neighbours.Clear();
826 
827  // remove the clip model from the static physics object
828  clipModelId = shard->clipModel->GetId();
829  physicsObj.SetClipModel( NULL, 1.0f, clipModelId, false );
830 
831  origin = shard->clipModel->GetOrigin();
832  axis = shard->clipModel->GetAxis();
833 
834  // set the dropped time for fading
835  shard->droppedTime = time;
836 
837  dir2 = origin - point;
838  dist = dir2.Normalize();
839  f = dist > maxShatterRadius ? 1.0f : idMath::Sqrt( dist - minShatterRadius ) * ( 1.0f / idMath::Sqrt( maxShatterRadius - minShatterRadius ) );
840 
841  // setup the physics
842  shard->physicsObj.SetSelf( this );
843  shard->physicsObj.SetClipModel( shard->clipModel, density );
844  shard->physicsObj.SetMass( shardMass );
845  shard->physicsObj.SetOrigin( origin );
846  shard->physicsObj.SetAxis( axis );
848  shard->physicsObj.SetFriction( 0.6f, 0.6f, friction );
852  shard->physicsObj.ApplyImpulse( 0, origin, impulse * linearVelocityScale * dir );
853  shard->physicsObj.SetAngularVelocity( dir.Cross( dir2 ) * ( f * angularVelocityScale ) );
854 
855  shard->clipModel->SetId( clipModelId );
856 
858 }
859 
860 /*
861 ================
862 idBrittleFracture::Shatter
863 ================
864 */
865 void idBrittleFracture::Shatter( const idVec3 &point, const idVec3 &impulse, const int time ) {
866  int i;
867  idVec3 dir;
868  shard_t *shard;
869  float m;
870 
871  if ( gameLocal.isServer ) {
872  idBitMsg msg;
873  byte msgBuf[MAX_EVENT_PARAM_SIZE];
874 
875  msg.Init( msgBuf, sizeof( msgBuf ) );
876  msg.BeginWriting();
877  msg.WriteFloat( point[0] );
878  msg.WriteFloat( point[1] );
879  msg.WriteFloat( point[2] );
880  msg.WriteFloat( impulse[0] );
881  msg.WriteFloat( impulse[1] );
882  msg.WriteFloat( impulse[2] );
883  ServerSendEvent( EVENT_SHATTER, &msg, true, -1 );
884  }
885 
886  if ( time > ( gameLocal.time - SHARD_ALIVE_TIME ) ) {
887  StartSound( "snd_shatter", SND_CHANNEL_ANY, 0, false, NULL );
888  }
889 
890  if ( !IsBroken() ) {
891  Break();
892  }
893 
894  if ( fxFracture.Length() ) {
895  idEntityFx::StartFx( fxFracture, &point, &GetPhysics()->GetAxis(), this, true );
896  }
897 
898  dir = impulse;
899  m = dir.Normalize();
900 
901  for ( i = 0; i < shards.Num(); i++ ) {
902  shard = shards[i];
903 
904  if ( shard->droppedTime != -1 ) {
905  continue;
906  }
907 
908  if ( ( shard->clipModel->GetOrigin() - point ).LengthSqr() > Square( maxShatterRadius ) ) {
909  continue;
910  }
911 
912  DropShard( shard, point, dir, m, time );
913  }
914 
915  DropFloatingIslands( point, impulse, time );
916 }
917 
918 /*
919 ================
920 idBrittleFracture::DropFloatingIslands
921 ================
922 */
923 void idBrittleFracture::DropFloatingIslands( const idVec3 &point, const idVec3 &impulse, const int time ) {
924  int i, j, numIslands;
925  int queueStart, queueEnd;
926  shard_t *curShard, *nextShard, **queue;
927  bool touchesEdge;
928  idVec3 dir;
929 
930  dir = impulse;
931  dir.Normalize();
932 
933  numIslands = 0;
934  queue = (shard_t **) _alloca16( shards.Num() * sizeof(shard_t **) );
935  for ( i = 0; i < shards.Num(); i++ ) {
936  shards[i]->islandNum = 0;
937  }
938 
939  for ( i = 0; i < shards.Num(); i++ ) {
940 
941  if ( shards[i]->droppedTime != -1 ) {
942  continue;
943  }
944 
945  if ( shards[i]->islandNum ) {
946  continue;
947  }
948 
949  queueStart = 0;
950  queueEnd = 1;
951  queue[0] = shards[i];
952  shards[i]->islandNum = numIslands+1;
953  touchesEdge = false;
954 
955  if ( shards[i]->atEdge ) {
956  touchesEdge = true;
957  }
958 
959  for ( curShard = queue[queueStart]; queueStart < queueEnd; curShard = queue[++queueStart] ) {
960 
961  for ( j = 0; j < curShard->neighbours.Num(); j++ ) {
962 
963  nextShard = curShard->neighbours[j];
964 
965  if ( nextShard->droppedTime != -1 ) {
966  continue;
967  }
968 
969  if ( nextShard->islandNum ) {
970  continue;
971  }
972 
973  queue[queueEnd++] = nextShard;
974  nextShard->islandNum = numIslands+1;
975 
976  if ( nextShard->atEdge ) {
977  touchesEdge = true;
978  }
979  }
980  }
981  numIslands++;
982 
983  // if the island is not connected to the world at any edges
984  if ( !touchesEdge ) {
985  for ( j = 0; j < queueEnd; j++ ) {
986  DropShard( queue[j], point, dir, 0.0f, time );
987  }
988  }
989  }
990 }
991 
992 /*
993 ================
994 idBrittleFracture::Break
995 ================
996 */
998  fl.takedamage = false;
1000 }
1001 
1002 /*
1003 ================
1004 idBrittleFracture::IsBroken
1005 ================
1006 */
1007 bool idBrittleFracture::IsBroken( void ) const {
1008  return ( fl.takedamage == false );
1009 }
1010 
1011 /*
1012 ================
1013 idBrittleFracture::Killed
1014 ================
1015 */
1016 void idBrittleFracture::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
1017  if ( !disableFracture ) {
1018  ActivateTargets( this );
1019  Break();
1020  }
1021 }
1022 
1023 /*
1024 ================
1025 idBrittleFracture::AddDamageEffect
1026 ================
1027 */
1028 void idBrittleFracture::AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName ) {
1029  if ( !disableFracture ) {
1030  ProjectDecal( collision.c.point, collision.c.normal, gameLocal.time, damageDefName );
1031  }
1032 }
1033 
1034 /*
1035 ================
1036 idBrittleFracture::Fracture_r
1037 ================
1038 */
1040  int i, j, bestPlane;
1041  float a, c, s, dist, bestDist;
1042  idVec3 origin;
1043  idPlane windingPlane, splitPlanes[2];
1044  idMat3 axis, axistemp;
1045  idFixedWinding back;
1046  idTraceModel trm;
1047  idClipModel *clipModel;
1048 
1049  while( 1 ) {
1050  origin = w.GetCenter();
1051  w.GetPlane( windingPlane );
1052 
1053  if ( w.GetArea() < maxShardArea ) {
1054  break;
1055  }
1056 
1057  // randomly create a split plane
1058  axis[2] = windingPlane.Normal();
1059 #ifdef _D3XP
1060  if ( isXraySurface ) {
1061  a = idMath::TWO_PI / 2.f;
1062  }
1063  else {
1065  }
1066 #else
1068 #endif
1069  c = cos( a );
1070  s = -sin( a );
1071  axis[2].NormalVectors( axistemp[0], axistemp[1] );
1072  axis[0] = axistemp[ 0 ] * c + axistemp[ 1 ] * s;
1073  axis[1] = axistemp[ 0 ] * s + axistemp[ 1 ] * -c;
1074 
1075  // get the best split plane
1076  bestDist = 0.0f;
1077  bestPlane = 0;
1078  for ( i = 0; i < 2; i++ ) {
1079  splitPlanes[i].SetNormal( axis[i] );
1080  splitPlanes[i].FitThroughPoint( origin );
1081  for ( j = 0; j < w.GetNumPoints(); j++ ) {
1082  dist = splitPlanes[i].Distance( w[j].ToVec3() );
1083  if ( dist > bestDist ) {
1084  bestDist = dist;
1085  bestPlane = i;
1086  }
1087  }
1088  }
1089 
1090  // split the winding
1091  if ( !w.Split( &back, splitPlanes[bestPlane] ) ) {
1092  break;
1093  }
1094 
1095  // recursively create shards for the back winding
1096  Fracture_r( back );
1097  }
1098 
1099  // translate the winding to it's center
1100  origin = w.GetCenter();
1101  for ( j = 0; j < w.GetNumPoints(); j++ ) {
1102  w[j].ToVec3() -= origin;
1103  }
1104  w.RemoveEqualPoints();
1105 
1106  trm.SetupPolygon( w );
1107  trm.Shrink( CM_CLIP_EPSILON );
1108  clipModel = new idClipModel( trm );
1109 
1110  physicsObj.SetClipModel( clipModel, 1.0f, shards.Num() );
1111  physicsObj.SetOrigin( GetPhysics()->GetOrigin() + origin, shards.Num() );
1112  physicsObj.SetAxis( GetPhysics()->GetAxis(), shards.Num() );
1113 
1114  AddShard( clipModel, w );
1115 }
1116 
1117 /*
1118 ================
1119 idBrittleFracture::CreateFractures
1120 ================
1121 */
1123  int i, j, k;
1124  const modelSurface_t *surf;
1125  const idDrawVert *v;
1126  idFixedWinding w;
1127 
1128  if ( !renderModel ) {
1129  return;
1130  }
1131 
1132  physicsObj.SetSelf( this );
1133  physicsObj.SetOrigin( GetPhysics()->GetOrigin(), 0 );
1134  physicsObj.SetAxis( GetPhysics()->GetAxis(), 0 );
1135 
1136 #ifdef _D3XP
1137  if ( isXraySurface ) {
1138  for ( i = 0; i < 1 /*renderModel->NumSurfaces()*/; i++ ) {
1139  surf = renderModel->Surface( i );
1140  material = surf->shader;
1141 
1142  w.Clear();
1143 
1144  int k = 0;
1145  v = &surf->geometry->verts[k];
1146  w.AddPoint( v->xyz );
1147  w[k].s = v->st[0];
1148  w[k].t = v->st[1];
1149 
1150  k = 1;
1151  v = &surf->geometry->verts[k];
1152  w.AddPoint( v->xyz );
1153  w[k].s = v->st[0];
1154  w[k].t = v->st[1];
1155 
1156  k = 3;
1157  v = &surf->geometry->verts[k];
1158  w.AddPoint( v->xyz );
1159  w[k].s = v->st[0];
1160  w[k].t = v->st[1];
1161 
1162  k = 2;
1163  v = &surf->geometry->verts[k];
1164  w.AddPoint( v->xyz );
1165  w[k].s = v->st[0];
1166  w[k].t = v->st[1];
1167 
1168  Fracture_r( w );
1169  }
1170 
1171  }
1172  else {
1173  for ( i = 0; i < 1 /*renderModel->NumSurfaces()*/; i++ ) {
1174  surf = renderModel->Surface( i );
1175  material = surf->shader;
1176 
1177  for ( j = 0; j < surf->geometry->numIndexes; j += 3 ) {
1178  w.Clear();
1179  for ( k = 0; k < 3; k++ ) {
1180  v = &surf->geometry->verts[ surf->geometry->indexes[ j + 2 - k ] ];
1181  w.AddPoint( v->xyz );
1182  w[k].s = v->st[0];
1183  w[k].t = v->st[1];
1184  }
1185  Fracture_r( w );
1186  }
1187  }
1188  }
1189 #else
1190  for ( i = 0; i < 1 /*renderModel->NumSurfaces()*/; i++ ) {
1191  surf = renderModel->Surface( i );
1192  material = surf->shader;
1193 
1194  for ( j = 0; j < surf->geometry->numIndexes; j += 3 ) {
1195  w.Clear();
1196  for ( k = 0; k < 3; k++ ) {
1197  v = &surf->geometry->verts[ surf->geometry->indexes[ j + 2 - k ] ];
1198  w.AddPoint( v->xyz );
1199  w[k].s = v->st[0];
1200  w[k].t = v->st[1];
1201  }
1202  Fracture_r( w );
1203  }
1204  }
1205 #endif
1206 
1208  SetPhysics( &physicsObj );
1209 }
1210 
1211 /*
1212 ================
1213 idBrittleFracture::FindNeighbours
1214 ================
1215 */
1217  int i, j, k, l;
1218  idVec3 p1, p2, dir;
1219  idMat3 axis;
1220  idPlane plane[4];
1221 
1222  for ( i = 0; i < shards.Num(); i++ ) {
1223 
1224  shard_t *shard1 = shards[i];
1225  const idWinding &w1 = shard1->winding;
1226  const idVec3 &origin1 = shard1->clipModel->GetOrigin();
1227  const idMat3 &axis1 = shard1->clipModel->GetAxis();
1228 
1229  for ( k = 0; k < w1.GetNumPoints(); k++ ) {
1230 
1231  p1 = origin1 + w1[k].ToVec3() * axis1;
1232  p2 = origin1 + w1[(k+1)%w1.GetNumPoints()].ToVec3() * axis1;
1233  dir = p2 - p1;
1234  dir.Normalize();
1235  axis = dir.ToMat3();
1236 
1237  plane[0].SetNormal( dir );
1238  plane[0].FitThroughPoint( p1 );
1239  plane[1].SetNormal( -dir );
1240  plane[1].FitThroughPoint( p2 );
1241  plane[2].SetNormal( axis[1] );
1242  plane[2].FitThroughPoint( p1 );
1243  plane[3].SetNormal( axis[2] );
1244  plane[3].FitThroughPoint( p1 );
1245 
1246  for ( j = 0; j < shards.Num(); j++ ) {
1247 
1248  if ( i == j ) {
1249  continue;
1250  }
1251 
1252  shard_t *shard2 = shards[j];
1253 
1254  for ( l = 0; l < shard1->neighbours.Num(); l++ ) {
1255  if ( shard1->neighbours[l] == shard2 ) {
1256  break;
1257  }
1258  }
1259  if ( l < shard1->neighbours.Num() ) {
1260  continue;
1261  }
1262 
1263  const idWinding &w2 = shard2->winding;
1264  const idVec3 &origin2 = shard2->clipModel->GetOrigin();
1265  const idMat3 &axis2 = shard2->clipModel->GetAxis();
1266 
1267  for ( l = w2.GetNumPoints()-1; l >= 0; l-- ) {
1268  p1 = origin2 + w2[l].ToVec3() * axis2;
1269  p2 = origin2 + w2[(l-1+w2.GetNumPoints())%w2.GetNumPoints()].ToVec3() * axis2;
1270  if ( plane[0].Side( p2, 0.1f ) == SIDE_FRONT && plane[1].Side( p1, 0.1f ) == SIDE_FRONT ) {
1271  if ( plane[2].Side( p1, 0.1f ) == SIDE_ON && plane[3].Side( p1, 0.1f ) == SIDE_ON ) {
1272  if ( plane[2].Side( p2, 0.1f ) == SIDE_ON && plane[3].Side( p2, 0.1f ) == SIDE_ON ) {
1273  shard1->neighbours.Append( shard2 );
1274  shard1->edgeHasNeighbour[k] = true;
1275  shard2->neighbours.Append( shard1 );
1276  shard2->edgeHasNeighbour[(l-1+w2.GetNumPoints())%w2.GetNumPoints()] = true;
1277  break;
1278  }
1279  }
1280  }
1281  }
1282  }
1283  }
1284 
1285  for ( k = 0; k < w1.GetNumPoints(); k++ ) {
1286  if ( !shard1->edgeHasNeighbour[k] ) {
1287  break;
1288  }
1289  }
1290  if ( k < w1.GetNumPoints() ) {
1291  shard1->atEdge = true;
1292  } else {
1293  shard1->atEdge = false;
1294  }
1295  }
1296 }
1297 
1298 /*
1299 ================
1300 idBrittleFracture::Event_Activate
1301 ================
1302 */
1304  disableFracture = false;
1305  if ( health <= 0 ) {
1306  Break();
1307  }
1308 }
1309 
1310 /*
1311 ================
1312 idBrittleFracture::Event_Touch
1313 ================
1314 */
1316  idVec3 point, impulse;
1317 
1318  if ( !IsBroken() ) {
1319  return;
1320  }
1321 
1322  if ( trace->c.id < 0 || trace->c.id >= shards.Num() ) {
1323  return;
1324  }
1325 
1326  point = shards[trace->c.id]->clipModel->GetOrigin();
1327  impulse = other->GetPhysics()->GetLinearVelocity() * other->GetPhysics()->GetMass();
1328 
1329  Shatter( point, impulse, gameLocal.time );
1330 }
1331 
1332 /*
1333 ================
1334 idBrittleFracture::ClientPredictionThink
1335 ================
1336 */
1338  // only think forward because the state is not synced through snapshots
1339  if ( !gameLocal.isNewFrame ) {
1340  return;
1341  }
1342 
1343  Think();
1344 }
1345 
1346 /*
1347 ================
1348 idBrittleFracture::ClientReceiveEvent
1349 ================
1350 */
1351 bool idBrittleFracture::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
1352  idVec3 point, dir;
1353 
1354  switch( event ) {
1355  case EVENT_PROJECT_DECAL: {
1356  point[0] = msg.ReadFloat();
1357  point[1] = msg.ReadFloat();
1358  point[2] = msg.ReadFloat();
1359  dir[0] = msg.ReadFloat();
1360  dir[1] = msg.ReadFloat();
1361  dir[2] = msg.ReadFloat();
1362  ProjectDecal( point, dir, time, NULL );
1363  return true;
1364  }
1365  case EVENT_SHATTER: {
1366  point[0] = msg.ReadFloat();
1367  point[1] = msg.ReadFloat();
1368  point[2] = msg.ReadFloat();
1369  dir[0] = msg.ReadFloat();
1370  dir[1] = msg.ReadFloat();
1371  dir[2] = msg.ReadFloat();
1372  Shatter( point, dir, time );
1373  return true;
1374  }
1375  default: {
1376  return idEntity::ClientReceiveEvent( event, time, msg );
1377  }
1378  }
1379  return false;
1380 }
void SetupPolygon(const idVec3 *v, const int count)
Definition: TraceModel.cpp:866
virtual ~idBrittleFracture(void)
void SetAngularVelocity(const idVec3 &newAngularVelocity, int id=0)
void SetClipModel(idClipModel *model, float density, int id=0, bool freeOld=true)
renderEntity_t renderEntity
Definition: Entity.h:371
void BeginWriting(void)
Definition: BitMsg.h:265
bool AddBounds(const idBounds &a)
Definition: Bounds.h:255
float GetFloat(const char *key, const char *defaultString="0") const
Definition: Dict.h:248
unsigned int dword
Definition: Lib.h:77
idMat3 ToMat3(void) const
Definition: Vector.cpp:195
idList< bool > edgeHasNeighbour
virtual srfTriangles_t * AllocSurfaceTriangles(int numVerts, int numIndexes) const =0
void WriteString(const char *string)
Definition: SaveGame.cpp:231
float Normalize(void)
Definition: Vector.h:646
void RemoveEqualPoints(const float epsilon=ON_EPSILON)
Definition: Winding.cpp:733
void SetId(int newId)
Definition: Clip.h:182
bool UpdateRenderEntity(renderEntity_s *renderEntity, const renderView_t *renderView) const
int GetInt(const char *key, const char *defaultString="0") const
Definition: Dict.h:252
void ApplyImpulse(const int id, const idVec3 &point, const idVec3 &impulse)
float GetArea(void) const
Definition: Winding.cpp:598
assert(prefInfo.fullscreenBtn)
virtual const idSoundShader * FindSound(const char *name, bool makeDefault=true)=0
const idVec3 & Normal(void) const
Definition: Plane.h:239
void Clear(void)
Definition: DrawVert.h:73
void ReadMaterial(const idMaterial *&material)
Definition: SaveGame.cpp:1132
int numVerts
Definition: Model.h:98
virtual bool ClientReceiveEvent(int event, int time, const idBitMsg &msg)
struct idEntity::entityFlags_s fl
float y
Definition: Vector.h:55
void SetColor(dword color)
Definition: DrawVert.h:99
const int MAX_EVENT_PARAM_SIZE
Definition: Game_local.h:132
const GLdouble * v
Definition: glext.h:2936
const idEventDef EV_Activate("activate","e")
bool isNewFrame
Definition: Game_local.h:333
void RemoveShard(int index)
virtual qhandle_t AddEntityDef(const renderEntity_t *re)=0
GLint location
Definition: glext.h:3631
#define const
Definition: getdate.c:251
float Distance(const idVec3 &v) const
Definition: Plane.h:324
idRandom random
Definition: Game_local.h:291
int Length(void) const
Definition: Str.h:702
void void void void void Error(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:783
void AssureSize(int newSize)
Definition: List.h:445
void WriteFloat(float f)
Definition: BitMsg.h:299
idVec3 xyz
Definition: DrawVert.h:42
void Write(const void *buffer, int len)
Definition: SaveGame.cpp:159
const idMat3 & GetAxis(void) const
Definition: Clip.h:210
void ReadWinding(idWinding &winding)
Definition: SaveGame.cpp:1048
GLenum GLsizei n
Definition: glext.h:3705
virtual void AddForce(idEntity *ent, int id, const idVec3 &point, const idVec3 &force)
int previousTime
Definition: Game_local.h:318
#define MASK_SOLID
Definition: Game_local.h:735
idVec3 tangents[2]
Definition: DrawVert.h:45
const idMaterial * shader
Definition: Model.h:146
static float ClampFloat(float min, float max, float value)
Definition: Math.h:893
virtual void AddSurface(modelSurface_t surface)=0
const char * GetName(void) const
Definition: DeclManager.h:140
Definition: Vector.h:316
case const float
Definition: Callbacks.cpp:62
void ReadBool(bool &value)
Definition: SaveGame.cpp:976
bool isServer
Definition: Game_local.h:326
void Event_Touch(idEntity *other, trace_t *trace)
virtual const idVec3 & GetLinearVelocity(int id=0) const =0
void WriteStaticObject(const idClass &obj)
Definition: SaveGame.cpp:348
static float Sqrt(float x)
Definition: Math.h:302
ID_INLINE T Square(T x)
Definition: Math.h:104
const int SHADERPARM_GREEN
Definition: RenderWorld.h:47
virtual void FreeModelDef(void)
Definition: Entity.cpp:1197
dword PackColor(const idVec4 &color)
Definition: Lib.cpp:147
const idVec3 & GetOrigin(void) const
Definition: Clip.h:206
void Clear(void)
Definition: Bounds.h:201
idPhysics_StaticMulti physicsObj
virtual const idMaterial * FindMaterial(const char *name, bool makeDefault=true)=0
bool tangentsCalculated
Definition: Model.h:92
bool IsBroken(void) const
GLdouble s
Definition: glext.h:2935
void SetNormal(const idVec3 &normal)
Definition: Plane.h:233
void Identity(void)
Definition: Matrix.h:591
idDict spawnArgs
Definition: Entity.h:122
idPhysics_RigidBody physicsObj
int i
Definition: process.py:33
void LittleBitField(void *bp, int elsize)
Definition: Lib.cpp:286
contactInfo_t c
deferredEntityCallback_t callback
Definition: RenderWorld.h:96
GLuint GLuint num
Definition: glext.h:5390
int Split(idFixedWinding *back, const idPlane &plane, const float epsilon=ON_EPSILON)
Definition: Winding.cpp:1484
void WriteMaterial(const idMaterial *material)
Definition: SaveGame.cpp:380
#define EVENT(event, function)
Definition: Class.h:53
void Init(byte *data, int length)
Definition: BitMsg.h:155
list l
Definition: prepare.py:17
virtual void ClientPredictionThink(void)
void WriteBool(const bool value)
Definition: SaveGame.cpp:222
virtual void InitEmpty(const char *name)=0
bool StartSoundShader(const idSoundShader *shader, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length)
Definition: Entity.cpp:1656
const int SHADERPARM_BLUE
Definition: RenderWorld.h:48
idVec2 st
Definition: DrawVert.h:43
bool noDynamicInteractions
Definition: RenderWorld.h:144
void Restore(idRestoreGame *savefile)
void SetSelf(idEntity *e)
virtual void VPCALL MinMax(float &min, float &max, const float *src, const int count)=0
Definition: Vector.h:52
#define FLOATSIGNBITSET(f)
Definition: Math.h:68
const int SHARD_FADE_START
idPhysics * GetPhysics(void) const
Definition: Entity.cpp:2607
int GetNumPoints(void) const
Definition: Winding.h:238
#define MAX_POINTS_ON_WINDING
Definition: Winding.h:279
void WriteWinding(const idWinding &winding)
Definition: SaveGame.cpp:291
GLuint index
Definition: glext.h:3476
const GLubyte * c
Definition: glext.h:4677
const char * GetString(const char *key, const char *defaultString="") const
Definition: Dict.h:240
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
void ReadFloat(float &value)
Definition: SaveGame.cpp:967
Definition: Vector.h:808
float RandomFloat(void)
Definition: Random.h:82
bool StartSound(const char *soundName, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length)
Definition: Entity.cpp:1622
void void Read(void *buffer, int len)
Definition: SaveGame.cpp:913
void SetPhysics(idPhysics *phys)
Definition: Entity.cpp:2574
void Shatter(const idVec3 &point, const idVec3 &impulse, const int time)
idList< idFixedWinding * > decals
void WriteFloat(const float value)
Definition: SaveGame.cpp:213
idBounds bounds
Definition: Model.h:87
virtual float GetMass(int id=-1) const =0
bool GetBool(const char *key, const char *defaultString="0") const
Definition: Dict.h:256
#define NULL
Definition: Lib.h:88
srfTriangles_t * geometry
Definition: Model.h:147
END_CLASS const int SHARD_ALIVE_TIME
virtual void Think(void)
const int GetContentFlags(void) const
Definition: Material.h:497
virtual void Clear(void)
Definition: Winding.h:398
virtual void Present(void)
bool IsAtRest(void) const
void ServerSendEvent(int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient) const
Definition: Entity.cpp:4897
virtual const modelSurface_t * Surface(int surfaceNum) const =0
void GetPlane(idVec3 &normal, float &dist) const
Definition: Winding.cpp:656
float ReadFloat(void) const
Definition: BitMsg.h:379
Definition: Plane.h:71
const idVec3 & GetGravity(void) const
#define CM_CLIP_EPSILON
void Fracture_r(idFixedWinding &w)
float x
Definition: Vector.h:54
int GetId(void) const
Definition: Clip.h:186
static bool ModelCallback(renderEntity_s *renderEntity, const renderView_t *renderView)
void DeleteContents(bool clear)
Definition: List.h:207
struct shard_s shard_t
idVec3 normal
Definition: DrawVert.h:44
virtual void UpdateEntityDef(qhandle_t entityHandle, const renderEntity_t *re)=0
void SetFriction(const float linear, const float angular, const float contact)
idGameLocal gameLocal
Definition: Game_local.cpp:64
void SetBool(const char *key, bool val)
Definition: Dict.h:196
bool RunPhysics(void)
Definition: Entity.cpp:2616
#define END_CLASS
Definition: Class.h:54
idRenderModel * hModel
Definition: RenderWorld.h:81
GLubyte GLubyte GLubyte a
Definition: glext.h:4662
idClipModel * clipModel
void SetAxis(const idMat3 &newAxis, int id=-1)
void ReadBounds(idBounds &bounds)
Definition: SaveGame.cpp:1038
void ProjectDecal(const idVec3 &point, const idVec3 &dir, const int time, const char *damageDefName)
virtual void FreeModel(idRenderModel *model)=0
void WriteInt(const int value)
Definition: SaveGame.cpp:168
idDeclManager * declManager
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: glext.h:4080
idEntity * entities[MAX_GENTITIES]
Definition: Game_local.h:275
void Shrink(const float m)
virtual bool ClientReceiveEvent(int event, int time, const idBitMsg &msg)
Definition: Entity.cpp:4988
void SetAxis(const idMat3 &newAxis, int id=-1)
static const float TWO_PI
Definition: Math.h:206
idFixedWinding winding
int health
Definition: Entity.h:134
void SetContents(int contents, int id=-1)
void ReadStaticObject(idClass &obj)
Definition: SaveGame.cpp:1098
void DropFloatingIslands(const idVec3 &point, const idVec3 &impulse, const int time)
int Append(const type &obj)
Definition: List.h:646
#define SIDE_ON
Definition: Plane.h:49
#define bits
Definition: Unzip.cpp:3797
idRenderModelManager * renderModelManager
Definition: Matrix.h:333
const int SHADERPARM_RED
Definition: RenderWorld.h:46
void AddShard(idClipModel *clipModel, idFixedWinding &w)
void SetClipMask(int mask, int id=-1)
GLuint id
Definition: glext.h:3103
const idMaterial * decalMaterial
tuple f
Definition: idal.py:89
bool IsCleared(void) const
Definition: Bounds.h:222
int Num(void) const
Definition: List.h:265
bool RemoveIndex(int index)
Definition: List.h:849
unsigned char byte
Definition: Lib.h:75
int modelDefHandle
Definition: Entity.h:372
const idMaterial * material
GLfloat * st
Definition: qgl.h:89
virtual void Killed(idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location)
idVec3 GetCenter(void) const
Definition: Winding.cpp:639
bool ShouldCreateBackSides(void) const
Definition: Material.h:412
idList< shard_t * > shards
#define CLASS_DECLARATION(nameofsuperclass, nameofclass)
Definition: Class.h:110
Definition: Str.h:116
idBounds bounds
Definition: RenderWorld.h:95
int droppedTime
glIndex_t * indexes
Definition: Model.h:102
void RestorePhysics(idPhysics *phys)
Definition: Entity.cpp:2596
void BecomeActive(int flags)
Definition: Entity.cpp:995
void RemoveIndex(int id=0, bool freeClipModel=true)
void WriteBounds(const idBounds &bounds)
Definition: SaveGame.cpp:280
const idEventDef EV_Remove("<immediateremove>", NULL)
idList< struct shard_s * > neighbours
virtual void ApplyImpulse(idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse)
GLint j
Definition: qgl.h:264
void SetGravity(const idVec3 &newGravity)
int numIndexes
Definition: Model.h:101
void Event_Activate(idEntity *activator)
const idDeclEntityDef * FindEntityDef(const char *name, bool makeDefault=true) const
idRenderWorld * gameRenderWorld
Definition: Game_local.cpp:55
void AddPoint(const idVec3 &v)
Definition: Winding.h:222
static idEntityFx * StartFx(const char *fx, const idVec3 *useOrigin, const idMat3 *useAxis, idEntity *ent, bool bind)
Definition: Fx.cpp:716
void SetClipModel(idClipModel *model, float density, int id=0, bool freeOld=true)
bool PostEventMS(const idEventDef *ev, int time)
Definition: Class.cpp:666
GLfloat GLfloat p
Definition: glext.h:4674
int thinkFlags
Definition: Entity.h:125
#define SIDE_FRONT
Definition: Plane.h:47
const idEventDef EV_Touch("<touch>","et")
void SetBouncyness(const float b)
void Zero(void)
Definition: Vector.h:415
float shaderParms[MAX_ENTITY_SHADER_PARMS]
Definition: RenderWorld.h:127
void ReadString(idStr &string)
Definition: SaveGame.cpp:985
void BecomeInactive(int flags)
Definition: Entity.cpp:1025
void CreateFractures(const idRenderModel *renderModel)
virtual void AddDamageEffect(const trace_t &collision, const idVec3 &velocity, const char *damageDefName)
void ReadInt(int &value)
Definition: SaveGame.cpp:922
void ActivateTargets(idEntity *activator) const
Definition: Entity.cpp:3650
void SetContents(int contents, int id=-1)
idClipModel * GetClipModel(int id=0) const
idDrawVert * verts
Definition: Model.h:99
void DropShard(shard_t *shard, const idVec3 &point, const idVec3 &dir, const float impulse, const int time)
void SetOrigin(const idVec3 &newOrigin, int id=-1)
void SetOrigin(const idVec3 &newOrigin, int id=-1)
bool Evaluate(int timeStepMSec, int endTimeMSec)
void FitThroughPoint(const idVec3 &p)
Definition: Plane.h:297
void SetNumPoints(int n)
Definition: Winding.h:242
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: glext.h:4080
virtual idRenderModel * AllocModel()=0
void SetMass(float mass, int id=-1)
void Clear(void)
Definition: List.h:184
idSIMDProcessor * SIMDProcessor
Definition: Simd.cpp:43
void Save(idSaveGame *savefile) const
virtual int NumSurfaces() const =0