Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
shattersystem.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WWPhys *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/shattersystem.cpp $*
26 * *
27 * Original Author:: Greg Hjelstrom *
28 * *
29 * $Author:: Greg_h $*
30 * *
31 * $Modtime:: 12/03/01 4:57p $*
32 * *
33 * $Revision:: 11 $*
34 * *
35 *---------------------------------------------------------------------------------------------*
36 * Functions: *
37 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
38
39#include "shattersystem.h"
40#include "assetmgr.h"
41#include "mesh.h"
42#include "meshmdl.h"
43#include "dynamesh.h"
44#include "htree.h"
45#include "plane.h"
46#include "simplevec.h"
47#include "wwstring.h"
48#include "vp.h"
49#include "meshmatdesc.h"
50#include <stdlib.h>
51
52/*
53** Debug logging for the shatter system
54*/
55#define SHATTER_DEBUG_LOG_ENABLED 0
56#if (SHATTER_DEBUG_LOG_ENABLED)
57#define SHATTER_DEBUG_SAY(x) WWDEBUG_SAY(x)
58#else
59#define SHATTER_DEBUG_SAY(x)
60#endif
61
62
63
64#define SHATTER_PATTERN_FORMAT "ShatterPlanes%d"
65
66#define BPT_FRONT 0x01
67#define BPT_BACK 0x02
68#define BPT_ON 0x04
69#define BPT_BOTH 0x08
70#define BPT_EPSILON 0.0001f
71#define BPT_COINCIDENCE_EPSILON 0.000001f
72
73
78{
79public:
82
84
85 /*
86 ** NOTE: currently I do not fully support stage 1 textures or texture arrays in any pass.
87 ** The uv coordinates will be computed but the textures will not be set up.
88 */
92// Vector3i * UVIndexArray[MeshMatDescClass::MAX_PASSES];
93};
94
95
96
102{
103public:
104
105 VertexClass(void);
106 VertexClass(const VertexClass & that);
107 VertexClass & operator = (const VertexClass & that);
108
109 int Which_Side(const PlaneClass & plane) const;
110
113
118
119 static void Lerp(const VertexClass & v0,const VertexClass & v1,float lerp,VertexClass * res);
120 static void Intersect_Plane(const VertexClass & v0,const VertexClass & v1,const PlaneClass & plane,VertexClass * res);
121};
122
128{
129public:
130
131 enum { BPT_POLY_MAX_VERTS = 24 };
132
133 PolygonClass(void);
134 PolygonClass(const PolygonClass & that);
135 PolygonClass(const VertexClass * points, int num);
136 PolygonClass & operator = (const PolygonClass & that);
137
138 // Accessors
139 const VertexClass & operator[] (int i) const { return Verts[i]; }
140 VertexClass & operator[] (int i) { return Verts[i]; }
141
142 int Get_Vertex_Count(void) const { return NumVerts; }
143 int Get_Material_ID(void) const { return MaterialId; }
144 const PlaneClass & Get_Plane(void) const { return Plane; }
145
146 void Set_Vertex_Count(int count) { NumVerts = count; }
147 void Set_Material_Id(int id) { MaterialId = id; }
148 void Set_Plane(const PlaneClass & plane) { Plane = plane; }
149
150 // Operations
151 void Compute_Plane(void);
152 int Which_Side(const PlaneClass & plane) const;
153 void Split(const PlaneClass & plane,PolygonClass & front,PolygonClass & back) const;
154 bool Is_Degenerate(void);
155 bool Salvage_Degenerate(void);
156
157public:
158
162
164
165};
166
181{
182public:
183 BSPClass(HTreeClass * tree,int bone_index,int & leaf_index);
184 ~BSPClass(void);
185
186 const PlaneClass & Get_Plane(void) { return Plane; }
187 BSPClass * Get_Front_Child(void) { return Front; }
188 BSPClass * Get_Back_Child(void) { return Back; }
189
190 void Clip_Polygon(const PolygonClass & poly);
191
192protected:
193
194 void Set_Plane_From_Transform(const Matrix3D & tm);
195
196 PlaneClass Plane; // plane equation
197 BSPClass * Front; // pointers to child clipping planes
199 int FrontLeafIndex; // if a leaf node, has two mesh fragment indices
201};
202
203
204/***********************************************************************************************
205**
206** Static Variables
207** ShatterPatterns - Array of BSP-trees for clipping (shattering) messhes
208** ClippedPolygonPool - Array of polygon arrays, one per leaf.
209** MeshFragments - Array of resultant clipped meshes, one per leaf
210** TmpVertPositions - Workspace for transforming vertex positions
211** TmpVertNormals - Workspace for transforming vertex normals
212**
213***********************************************************************************************/
214
215enum { MAX_MESH_FRAGMENTS = 32 };
216static SimpleDynVecClass<BSPClass *> ShatterPatterns;
219static SimpleVecClass<Vector3> TmpVertPositions(256);
220static SimpleVecClass<Vector3> TmpVertNormals(256);
221
222
223/***********************************************************************************************
224**
225** Local static utility functions
226**
227***********************************************************************************************/
228static Vector3 * _get_temp_vertex_position_array(int count)
229{
230 if (TmpVertPositions.Length() < count) {
231 TmpVertPositions.Resize(count);
232 }
233 return &(TmpVertPositions[0]);
234}
235
236static Vector3 * _get_temp_vertex_normal_array(int count)
237{
238 if (TmpVertNormals.Length() < count) {
239 TmpVertNormals.Resize(count);
240 }
241 return &(TmpVertNormals[0]);
242}
243
244/***********************************************************************************************
245**
246** MeshMtlParamsClass Implementation
247**
248***********************************************************************************************/
250{
251 PassCount = model->Get_Pass_Count();
252
253 for (int ipass=0; ipass<MeshMatDescClass::MAX_PASSES; ipass++) {
254
255 DCG[ipass] = model->Get_DCG_Array(ipass);
256 DIG[ipass] = model->Get_DIG_Array(ipass);
257// UVIndexArray[ipass] = model->Get_UVIndex_Array(ipass,false);
258 for (int istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
259 UV[ipass][istage] = const_cast<Vector2*>(model->Get_UV_Array(ipass,istage));
260 }
261 }
262}
263
267
268
269/***********************************************************************************************
270**
271** VertexClass Implementation
272**
273***********************************************************************************************/
275 Position(0,0,0),
276 Normal(0,0,1),
277 PassCount(0)
278{
279 for (int ipass=0; ipass<MeshMatDescClass::MAX_PASSES; ipass++) {
280 DCG[ipass]=0xffffffff;
281 DIG[ipass]=0xffffffff;
282 for (int istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
283 TexCoord[ipass][istage].Set(0,0);
284 }
285 }
286}
287
289{
290 Position = that.Position;
291 Normal = that.Normal;
292 PassCount = that.PassCount;
293
294 for (int ipass=0; ipass<PassCount; ipass++) {
295 DCG[ipass] = that.DCG[ipass];
296 DIG[ipass] = that.DIG[ipass];
297 for (int istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
298 TexCoord[ipass][istage] = that.TexCoord[ipass][istage];
299 }
300 }
301}
302
304{
305 if (this != &that) {
306 Position = that.Position;
307 Normal = that.Normal;
308 PassCount = that.PassCount;
309 for (int ipass=0; ipass<PassCount; ipass++) {
310 DCG[ipass] = that.DCG[ipass];
311 DIG[ipass] = that.DIG[ipass];
312 for (int istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
313 TexCoord[ipass][istage] = that.TexCoord[ipass][istage];
314 }
315 }
316 }
317 return *this;
318}
319
321(
322 const VertexClass & v0,
323 const VertexClass & v1,
324 float lerp,
325 VertexClass * res
326)
327{
328 assert(lerp >= -BPT_EPSILON);
329 assert(lerp <= 1.0 + BPT_EPSILON);
330 assert(v0.PassCount==v1.PassCount);
331 res->PassCount = v0.PassCount;
332
333 // interpolate position
334 Vector3::Lerp(v0.Position,v1.Position,lerp,&(res->Position));
335
336 // interpolate normal, renormalize
337 Vector3::Lerp(v0.Normal,v1.Normal,lerp,&(res->Normal));
338 res->Normal.Normalize();
339
340 // interpolate material properies
341 for (int ipass=0; ipass<v0.PassCount; ipass++) {
342 Vector4 dcg_v0=DX8Wrapper::Convert_Color(v0.DCG[ipass]);
343 Vector4 dcg_v1=DX8Wrapper::Convert_Color(v1.DCG[ipass]);
344 Vector4 dig_v0=DX8Wrapper::Convert_Color(v0.DIG[ipass]);
345 Vector4 dig_v1=DX8Wrapper::Convert_Color(v1.DIG[ipass]);
346 Vector4::Lerp(dcg_v0,dcg_v1,res->DCG[ipass]);
347 Vector4::Lerp(dig_v0,dig_v1,res->DIG[ipass]);
348// Vector4::Lerp(v0.DCG[ipass],v1.DCG[ipass],lerp,&(res->DCG[ipass]));
349// Vector4::Lerp(v0.DIG[ipass],v1.DIG[ipass],lerp,&(res->DIG[ipass]));
350 for (int istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
351 Vector2::Lerp(v0.TexCoord[ipass][istage],v1.TexCoord[ipass][istage],lerp,&(res->TexCoord[ipass][istage]));
352 }
353 }
354}
355
356int VertexClass::Which_Side(const PlaneClass & plane) const
357{
358 float d = Vector3::Dot_Product(plane.N,Position);
359 d -= plane.D;
360
361 if (d > BPT_EPSILON) {
362 return BPT_FRONT;
363 }
364
365 if (d < -BPT_EPSILON) {
366 return BPT_BACK;
367 }
368
369 return BPT_ON;
370}
371
373(
374 const VertexClass & p0,
375 const VertexClass & p1,
376 const PlaneClass & plane,
377 VertexClass * res
378)
379{
380 float alpha = 0.0f;
381 plane.Compute_Intersection(p0.Position,p1.Position,&alpha);
382 VertexClass::Lerp(p0,p1,alpha,res);
383}
384
385
386
387/***********************************************************************************************
388**
389** PolygonClass Implementation
390**
391***********************************************************************************************/
393 NumVerts(0)
394{
395}
396
398{
399 NumVerts = that.NumVerts;
400 for (int i=0;i<NumVerts;i++) {
401 Verts[i] = that.Verts[i];
402 }
403}
404
406{
407 NumVerts = num;
408 for (int i=0; i<NumVerts; i++) {
409 Verts[i] = points[i];
410 }
411}
412
414{
415 if (this != &that) {
416 MaterialId = that.MaterialId;
417 NumVerts = that.NumVerts;
418 Plane = that.Plane;
419 for (int i=0;i<NumVerts;i++) {
420 Verts[i] = that.Verts[i];
421 }
422 }
423 return * this;
424}
425
427{
428 double nx = 0;
429 double ny = 0;
430 double nz = 0;
431 double ax = 0;
432 double ay = 0;
433 double az = 0;
434
435 int i,j;
436
437 for (i=0; i<NumVerts; i++) {
438 j = (i+1) % NumVerts;
439
440 nx += (double)(Verts[i].Position.Y - Verts[j].Position.Y) * (double)(Verts[i].Position.Z + Verts[j].Position.Z);
441 ny += (double)(Verts[i].Position.Z - Verts[j].Position.Z) * (double)(Verts[i].Position.X + Verts[j].Position.X);
442 nz += (double)(Verts[i].Position.X - Verts[j].Position.X) * (double)(Verts[i].Position.Y + Verts[j].Position.Y);
443
444 ax += (double)Verts[i].Position.X;
445 ay += (double)Verts[i].Position.Y;
446 az += (double)Verts[i].Position.Z;
447 }
448
449 ax /= (double)NumVerts;
450 ay /= (double)NumVerts;
451 az /= (double)NumVerts;
452
453 double len = WWMath::Sqrt(nx*nx + ny*ny + nz*nz);
454 nx /= len;
455 ny /= len;
456 nz /= len;
457
458 Plane.Set(Vector3(nx,ny,nz),Vector3(ax,ay,az));
459}
460
461int PolygonClass::Which_Side(const PlaneClass & plane) const
462{
463 int side_mask = 0;
464 for (int i=0; i<NumVerts;i++) {
465 side_mask |= Verts[i].Which_Side(plane);
466 }
467
468 // check if all verts are "ON"
469 if (side_mask == BPT_ON) {
470 return BPT_ON;
471 }
472
473 // check if all verts are either "ON" or "FRONT"
474 if ((side_mask & ~(BPT_FRONT | BPT_ON)) == 0) {
475 return BPT_FRONT;
476 }
477
478 // check if all verts are either "ON" or "BACK"
479 if ((side_mask & ~(BPT_BACK | BPT_ON)) == 0) {
480 return BPT_BACK;
481 }
482
483 // otherwise, poly spans the plane.
484 return BPT_BOTH;
485}
486
487void PolygonClass::Split(const PlaneClass & plane,PolygonClass & front,PolygonClass & back) const
488{
489 front = *this;
490 back = *this;
491 front.NumVerts = back.NumVerts = 0;
492 assert(Which_Side(plane) == BPT_BOTH);
493
494 VertexClass point;
495 front.NumVerts = 0;
496 back.NumVerts = 0;
497
498 // find a vertex on one side or the other
499 int side = BPT_ON;
500 int i;
501 for (i = 0; (i < NumVerts) && ((side = Verts[i].Which_Side(plane)) == BPT_ON); i++);
502
503 // perform clipping
504 int iprev = i;
505 int sideprev = side;
506 int sidelastdefinite = 0;
507
508 i = (i+1) % NumVerts;
509
510 for (int j=0; j<NumVerts; j++) {
511
512 side = Verts[i].Which_Side(plane);
513
514 if (sideprev == BPT_FRONT) {
515
516 if (side == BPT_FRONT) {
517
518 // Previous vertex was in front of plane and this vertex is in
519 // front of the plane so we emit this vertex in the front poly
520 front.Verts[(front.NumVerts)++] = Verts[i];
521
522 } else if (side == BPT_ON) {
523
524 // Previous vert was in front, this vert is "on" so emit
525 // the vertex into the front poly.
526 sidelastdefinite = BPT_FRONT;
527 front.Verts[(front.NumVerts)++] = Verts[i];
528
529 } else { // side == BPT_BACK
530
531 // Previous vert was in front, this vert is behind, compute
532 // the intersection and emit the point in both the front
533 // and back polys. Then continue the edge into the back halfspace
534 VertexClass::Intersect_Plane(Verts[iprev],Verts[i],plane,&point);
535 front.Verts[(front.NumVerts)++] = point;
536 back.Verts[(back.NumVerts)++] = point;
537 back.Verts[(back.NumVerts)++] = Verts[i];
538
539 }
540
541 } else if (sideprev == BPT_BACK) {
542
543 if (side == BPT_FRONT) {
544
545 // segment is going from the back halfspace to the front halfspace
546 // compute the intersection and emit it in both polys, then continue
547 // the edge into the front halfspace.
548 VertexClass::Intersect_Plane(Verts[iprev],Verts[i],plane,&point);
549 back.Verts[(back.NumVerts)++] = point;
550 front.Verts[(front.NumVerts)++] = point;
551 front.Verts[(front.NumVerts)++] = Verts[i];
552
553 } else if (side == BPT_ON) {
554
555 // segment went from back halfspace to "on" the plane. Emit
556 // the vertex into the back poly and remember that we came
557 // from the back halfspace.
558 sidelastdefinite = BPT_BACK;
559 back.Verts[(back.NumVerts)++] = Verts[i];
560
561 } else { // side == BPT_BACK
562
563 // segment is completely in the back halfspace, just emit the
564 // vertex into the back poly
565 back.Verts[(back.NumVerts)++] = Verts[i];
566
567 }
568
569 } else if (sideprev == BPT_ON) {
570
571 if (side == BPT_FRONT) {
572
573 // segment is on the plane
574 if (sidelastdefinite == BPT_BACK) {
575 front.Verts[(front.NumVerts)++] = Verts[iprev];
576 }
577 front.Verts[(front.NumVerts)++] = Verts[i];
578
579 } else if (side == BPT_ON) {
580
581 if (sidelastdefinite == BPT_FRONT) {
582 front.Verts[(front.NumVerts)++] = Verts[i];
583 } else {
584 back.Verts[(back.NumVerts)++] = Verts[i];
585 }
586
587 } else { // side == BPT_BACK
588
589 if (sidelastdefinite == BPT_FRONT) {
590 back.Verts[(back.NumVerts)++] = Verts[iprev];
591 }
592 back.Verts[(back.NumVerts)++] = Verts[i];
593 }
594 } else {
595 WWASSERT_PRINT(0,"PolygonClass::Split : invalid side\n");
596 }
597
598 sideprev = side;
599 iprev = i;
600 i = (i+1)%NumVerts;
601
602 }
603
604 front.Compute_Plane();
605 back.Compute_Plane();
606
607 // check the two polygons
608 if (front.Is_Degenerate()) {
609 front.Salvage_Degenerate();
610 }
611
612 if (back.Is_Degenerate()) {
613 back.Salvage_Degenerate();
614 }
615}
616
617
619{
620 int i,j;
621
622 if (NumVerts <= 2) {
623 WWDEBUG_SAY(("Degenerate Poly - fewer than 3 vertices\r\n"));
624 return true;
625 }
626
627 for (i=0; i<NumVerts; i++) {
628 for (j = i+1; j < NumVerts; j++) {
629
630 float delta = (Verts[i].Position - Verts[j].Position).Length();
631 if (delta < BPT_COINCIDENCE_EPSILON) {
632 WWDEBUG_SAY(("Degenerate Poly - coincident vertices!\r\n"));
633 return true;
634 }
635 }
636 }
637
638 for (i=0; i<NumVerts; i++) {
639 int side = Verts[i].Which_Side(Plane);
640 if (side != BPT_ON) {
641
642 // hmmm, try to recalculate the plane, if it is still bad, then give up
644
645 if (Verts[i].Which_Side(Plane) != BPT_ON) {
646 WWDEBUG_SAY(("Degenerate Poly - invalid plane!\r\n"));
647 return true;
648 }
649 }
650 }
651
652 return false;
653}
654
656{
657 /*
658 ** About all we can do is combine sequential vertices which are co-incident
659 */
660 int i = 0;
661 while (i < NumVerts) {
662
663 float delta = (Verts[i].Position - Verts[i+1].Position).Length();
664 if (delta < BPT_COINCIDENCE_EPSILON) {
665
666 for (int j=i+1; j<NumVerts-1; j++) {
667 Verts[j] = Verts[j+1];
668 }
669
670 NumVerts--;
671
672 } else {
673
674 i++;
675 }
676 }
677
678 return !Is_Degenerate();
679}
680
681
682/***********************************************************************************************
683**
684** BSPClass Implementation
685**
686***********************************************************************************************/
687
688BSPClass::BSPClass(HTreeClass * tree,int bone_index,int & leaf_index) :
689 Plane(0,0,1,0),
690 Front(NULL),
691 Back(NULL),
692 FrontLeafIndex(-1),
693 BackLeafIndex(-1)
694{
695 // initialize our plane equation from the transform
696 Set_Plane_From_Transform(tree->Get_Transform(bone_index));
697 int front = -1;
698 int back = -1;
699
700 // search for a front and back child of this bone
701 for (int ibone=0; ibone < tree->Num_Pivots(); ibone++) {
702 if (tree->Get_Parent_Index(ibone) == bone_index) {
703
704 // found a child, now see if it is the front or back child
705 Vector3 point = tree->Get_Transform(ibone).Get_Translation();
706 if (Plane.In_Front(point)) {
707 front = ibone;
708 } else {
709 back = ibone;
710 }
711
712 }
713 }
714
715 // Recurse if we have children, otherwise assign leaf indices
716 if (front != -1) {
717 Front = W3DNEW BSPClass(tree,front,leaf_index);
718 } else {
719 FrontLeafIndex = leaf_index++;
720 }
721
722 if (back != -1) {
723 Back = W3DNEW BSPClass(tree,back,leaf_index);
724 } else {
725 BackLeafIndex = leaf_index++;
726 }
727}
728
730{
731 if (Front != NULL) {
732 delete Front;
733 }
734 if (Back != NULL) {
735 delete Back;
736 }
737 Front = Back = NULL;
738}
739
741{
742 Plane.Set(tm.Get_Z_Vector(),tm.Get_Translation());
743}
744
746{
747 PolygonClass front_poly,back_poly;
748 front_poly.Set_Vertex_Count(0);
749 back_poly.Set_Vertex_Count(0);
750
751 switch(polygon.Which_Side(Plane))
752 {
753 case BPT_FRONT: case BPT_ON:
754 front_poly = polygon;
755 break;
756 case BPT_BACK:
757 back_poly = polygon;
758 break;
759 default:
760 polygon.Split(Plane,front_poly,back_poly);
761 break;
762 };
763
764 // Process the front halfspace: Recurse if we have a child clipping plane,
765 // otherwise add our polygons to our assigned clipping pool
766 if (Front == NULL) {
767 // We're a leaf node so put the polygons into the mesh fragment arrays
768 if (front_poly.Get_Vertex_Count() >= 3) {
769 ClipPools[FrontLeafIndex].Add(front_poly);
770 }
771 } else {
772 // Pass the polygons to our child for further clipping
773 if (front_poly.Get_Vertex_Count() >= 3) {
774 Front->Clip_Polygon(front_poly);
775 }
776 }
777
778 // Process the back halfspace:
779 if (Back==NULL) {
780 if (back_poly.Get_Vertex_Count() >= 3) {
781 ClipPools[BackLeafIndex].Add(back_poly);
782 }
783 } else {
784 if (back_poly.Get_Vertex_Count() >= 3) {
785 Back->Clip_Polygon(back_poly);
786 }
787 }
788}
789
790
791
792
793/***********************************************************************************************
794**
795** ShatterSystem Implementation - this is the interface with the outside world
796**
797** Transform meshes into space needed for shattering:
798** Vshatter = Mscale-to-unit * Mworld-shatterview * Mobj-world * Vobj
799**
800***********************************************************************************************/
802{
803 /*
804 ** Resize the Mesh Fragment pointer array to handle the maximum number
805 ** of mesh fragments.
806 */
807 MeshFragments.Resize(MAX_MESH_FRAGMENTS);
808
809 /*
810 ** Search for ShatterPattern hierarchy tree objects, beginning with ShatterPattern00
811 ** Create a BSP structure for each one.
812 */
813 StringClass htree_name;
814 htree_name.Format(SHATTER_PATTERN_FORMAT,0);
815
817 return; // WorldBuilderTool doesn't initialize the asset manager. jba.
818#if 1
819 HTreeClass *htree = NULL;
820#else
821 HTreeClass * htree = WW3DAssetManager::Get_Instance()->Get_HTree(htree_name);
822#endif
823 while (htree != NULL) {
824 if ((htree->Num_Pivots() > 1) && (htree->Num_Pivots() < MAX_MESH_FRAGMENTS)) {
825 int leaf_counter = 0;
826 htree->Base_Update(Matrix3D(1));
827 ShatterPatterns.Add(W3DNEW BSPClass(htree,1,leaf_counter));
828 }
829
830 /*
831 ** Try to load the next tree
832 */
833 htree_name.Format(SHATTER_PATTERN_FORMAT,ShatterPatterns.Count());
834 htree = WW3DAssetManager::Get_Instance()->Get_HTree(htree_name);
835 }
836}
837
839{
840 /*
841 ** Release all mesh fragments
842 */
844
845 /*
846 ** Release any loaded BSP trees
847 */
848 for (int i=0; i<ShatterPatterns.Count(); i++) {
849 delete ShatterPatterns[i];
850 ShatterPatterns[i] = NULL;
851 }
852 ShatterPatterns.Delete_All();
853}
854
855
856void ShatterSystem::Shatter_Mesh(MeshClass * mesh,const Vector3 & point,const Vector3 & direction)
857{
858 if (ShatterPatterns.Count() == 0) {
859 return ;
860 }
861
862 int ivert,ipoly;
863 int ipass,istage;
864
865 /*
866 ** Reset the temporary clip arrays
867 ** Release any old mesh fragment render objects
868 */
871
872 /*
873 ** Verify that this mesh meets the criteria for being shattered
874 ** - it has a maximum of two passes
875 ** - it uses only one vertex material per pass
876 ** - it uses only one shader per pass
877 ** - it uses only one texture per pass
878 */
879 MeshModelClass * model = mesh->Get_Model();
881 WWDEBUG_SAY(("Failed to shatter model: %s. Too many passes (%d)\n",model->Get_Name(),model->Get_Pass_Count()));
882 REF_PTR_RELEASE(model);
883 return;
884 }
885 for (ipass=0; ipass<model->Get_Pass_Count(); ipass++) {
886 if (model->Has_Material_Array(ipass) || model->Has_Shader_Array(ipass)) {
887 WWDEBUG_SAY(("Failed to shatter model: %s. It has shader or material arrays\n",model->Get_Name()));
888 REF_PTR_RELEASE(model);
889 return;
890 }
891
892 for (istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
893 if (model->Has_Texture_Array(ipass,istage)) {
894 WWDEBUG_SAY(("Failed to shatter model: %s. Texture array in pass: %d stage: %d\n",model->Get_Name(),ipass,istage));
895 REF_PTR_RELEASE(model);
896 return;
897 }
898 }
899 }
900
901 /*
902 ** Grab a random shatter pattern
903 */
904 BSPClass * clipper = ShatterPatterns[rand() % ShatterPatterns.Count()];
905
906 /*
907 ** Compute transforms which take vertices from mesh-space to shatter-space
908 ** and back again. Transform polygons into "shatter-space", clip, then
909 ** transform the results back out
910 **
911 ** Take vertices from obj-space to shatter space:
912 ** Vshatter = Mscale-to-unit * Mworld-shatterview * Mobj-world * Vobj
913 **
914 ** Clip the polygons to the BSP
915 ** Vclipped = BSP_CLIP(Vshatter)
916 **
917 ** Next, take the verts back to object space:
918 ** Vobjclip = Inverse(Mscale-to-unit * Mworld-shatter * Mobj-world) * Vclipped
919 ** = Inv(Mobj-world)*Inv(Mworld-shatter)*Inv(Mscl-to-unit) * Vclipped
920 **
921 ** Next, create separate, re-centered meshes
922 ** Vnewobj = Mold-obj-to-new-obj * Vobjclip
923 */
924
925 /*
926 ** Object-space to world-space transform
927 */
928 Matrix3D Mobj_to_world = mesh->Get_Transform();
929
930 /*
931 ** World-space to shatter-space transform
932 */
933 Matrix3D Mshatter_to_world;
934 Matrix3D Mworld_to_shatter;
935 Mshatter_to_world.Look_At(point,point+direction,0.0f); // TODO: could put random roll
936 Mshatter_to_world.Get_Orthogonal_Inverse(Mworld_to_shatter);
937
938 /*
939 ** Final pair of matrices
940 */
941 Matrix3D Mobj_to_shatter;
942 Matrix3D Mshatter_to_obj;
943
944 Matrix3D::Multiply(Mworld_to_shatter,Mobj_to_world,&Mobj_to_shatter);
945 Mobj_to_shatter.Get_Orthogonal_Inverse(Mshatter_to_obj);
946
947 /*
948 ** Scaling matrices. This could be simpler if Matrix3D had a full inverse function.
949 */
950 SphereClass sphere;
951 model->Get_Bounding_Sphere(&sphere);
952
953 float scale_factor = 5.0f / sphere.Radius; // mesh scales to 5x shatter pattern.
954 Matrix3D Mscale_to_shatter(1);
955 Matrix3D Mscale_from_shatter(1);
956 Mscale_to_shatter.Scale(scale_factor);
957 Mscale_from_shatter.Scale(1.0f / scale_factor);
958
959 Matrix3D::Multiply(Mscale_to_shatter,Mobj_to_shatter,&Mobj_to_shatter);
960 Matrix3D::Multiply(Mshatter_to_obj,Mscale_from_shatter,&Mshatter_to_obj);
961
962 /*
963 ** Grab the arrays out of the mesh and transform verts and vnorms
964 ** into "shatter-space"
965 */
966 const TriIndex * polys = model->Get_Polygon_Array();
967 const Vector3 * src_verts = model->Get_Vertex_Array();
968 const Vector3 * src_vnorms = model->Get_Vertex_Normal_Array();
969
970 Vector3 * verts = _get_temp_vertex_position_array(model->Get_Vertex_Count());
971 VectorProcessorClass::Transform(verts,src_verts,Mobj_to_shatter,model->Get_Vertex_Count());
972
973 /*
974 ** Build a description of the material parameters for the mesh
975 */
976 MeshMtlParamsClass mtl_params(model);
977
978
979 SHATTER_DEBUG_SAY(("****************************************************\n"));
980 SHATTER_DEBUG_SAY((" Clipping model: %s\n",model->Get_Name()));
981 SHATTER_DEBUG_SAY(("****************************************************\n"));
982
983 /*
984 ** Pass each polygon of the source model through the BSP clipper
985 */
986 for (ipoly=0; ipoly<model->Get_Polygon_Count(); ipoly++) {
987
988 /*
989 ** Set up a PolygonClass for polygon 'i' in the mesh
990 */
991 SHATTER_DEBUG_SAY(("Passing polygon %d to clipper.\n",ipoly));
992 PolygonClass polygon;
993 for (ivert=0; ivert<3; ivert++) {
994
995 int vert_index = polys[ipoly][ivert];
996 polygon.Verts[ivert].PassCount = mtl_params.PassCount;
997 polygon.Verts[ivert].Position = verts[vert_index];
998 polygon.Verts[ivert].Normal = src_vnorms[vert_index];
999 SHATTER_DEBUG_SAY(("position: %f %f %f\n",verts[vert_index].X,verts[vert_index].Y,verts[vert_index].Z));
1000 SHATTER_DEBUG_SAY(("normal: %f %f %f\n",src_vnorms[vert_index].X,src_vnorms[vert_index].Y,src_vnorms[vert_index].Z));
1001
1002 for (ipass=0; ipass<MeshMatDescClass::MAX_PASSES; ipass++) {
1003 if (mtl_params.DCG[ipass] != NULL) {
1004 polygon.Verts[ivert].DCG[ipass] = mtl_params.DCG[ipass][vert_index];
1005 SHATTER_DEBUG_SAY(("DCG: pass: %d : %f %f %f\n",ipass,mtl_params.DCG[ipass][vert_index].X,mtl_params.DCG[ipass][vert_index].Y,mtl_params.DCG[ipass][vert_index].Z));
1006 }
1007
1008 if (mtl_params.DIG[ipass] != NULL) {
1009 polygon.Verts[ivert].DIG[ipass] = mtl_params.DIG[ipass][vert_index];
1010 SHATTER_DEBUG_SAY(("DIG: pass: %d : %f %f %f\n",ipass,mtl_params.DIG[ipass][vert_index].X,mtl_params.DIG[ipass][vert_index].Y,mtl_params.DIG[ipass][vert_index].Z));
1011 }
1012
1013 for (istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
1014 if (mtl_params.UV[ipass][istage] != NULL) {
1015 polygon.Verts[ivert].TexCoord[ipass][istage] = mtl_params.UV[ipass][istage][vert_index];
1016 SHATTER_DEBUG_SAY(("UV pass: %d stage: %d: %f %f\n",ipass,istage,mtl_params.UV[ipass][istage][vert_index].X,mtl_params.UV[ipass][istage][vert_index].Y));
1017 }
1018 }
1019
1020/* if (mtl_params.UVIndexArray[ipass] != NULL) {
1021 int uv_index = mtl_params.UVIndexArray[ipass][ipoly][ivert];
1022 polygon.Verts[ivert].TexCoord[ipass][0] = mtl_params.UV[ipass][0][uv_index];
1023 SHATTER_DEBUG_SAY(("Per-Face UV pass: %d: %f %f\n",ipass,polygon.Verts[ivert].TexCoord[ipass][0].X,polygon.Verts[ivert].TexCoord[ipass][0].Y));
1024 }
1025*/ }
1026 }
1027 polygon.Set_Vertex_Count(3);
1028 polygon.Compute_Plane();
1029
1030 /*
1031 ** Pass it through the BSP
1032 */
1033 clipper->Clip_Polygon(polygon);
1034 }
1035
1036 /*
1037 ** convert the clipped polygons into meshes
1038 */
1039 Process_Clip_Pools(Mshatter_to_obj,mesh,mtl_params);
1040
1041 /*
1042 ** release resources
1043 */
1044 REF_PTR_RELEASE(model);
1045}
1046
1048{
1049 return MeshFragments.Count();
1050}
1051
1053{
1054 if (MeshFragments[fragment_index] != NULL) {
1055 MeshFragments[fragment_index]->Add_Ref();
1056 }
1057 return MeshFragments[fragment_index];
1058}
1059
1061{
1062 return MeshFragments[fragment_index];
1063}
1064
1066{
1067 // release any ref's to render objects
1068 for (int i=0; i<MeshFragments.Count(); i++) {
1069 REF_PTR_RELEASE(MeshFragments[i]);
1070 }
1071
1072 // reset array but don't resize
1073 MeshFragments.Delete_All(false);
1074}
1075
1077{
1078 for (int i=0; i<MAX_MESH_FRAGMENTS; i++) {
1079 // reset array but don't resize
1080 ClipPools[i].Delete_All(false);
1081 }
1082}
1083
1085(
1086 const Matrix3D & Mshatter_to_mesh,
1087 MeshClass * mesh,
1088 MeshMtlParamsClass & mtl_params
1089)
1090{
1091 /*
1092 ** Release any render objects we currently have and reset the array count
1093 */
1095
1096 /*
1097 ** Grab the model
1098 */
1099 MeshModelClass * model = mesh->Get_Model();
1100 WWASSERT(model != NULL);
1101
1102 /*
1103 ** Loop over all ClipPools and build a mesh for any that contain polygons
1104 */
1105 for (int ipool=0; ipool<MAX_MESH_FRAGMENTS; ipool++) {
1106
1107 if (ClipPools[ipool].Count() > 0) {
1108
1109 int ivert,ipoly,ipass,istage;
1110
1111 /*
1112 ** Count the verts and polys
1113 */
1114 int pcount = 0;
1115 int vcount = 0;
1116 for (ipoly=0;ipoly<ClipPools[ipool].Count();ipoly++) {
1117 int poly_vert_count = ClipPools[ipool][ipoly].Get_Vertex_Count();
1118 vcount += poly_vert_count;
1119 pcount += poly_vert_count-2;
1120 }
1121
1122 SHATTER_DEBUG_SAY(("****************************************************\n"));
1123 SHATTER_DEBUG_SAY((" Reassembling fragment %d of model: %s\n",ipool,model->Get_Name()));
1124 SHATTER_DEBUG_SAY((" polycount = %d vertexcount = %d\n",pcount,vcount));
1125 SHATTER_DEBUG_SAY(("****************************************************\n"));
1126
1127 /*
1128 ** Create the new mesh, install materials
1129 */
1130 DynamicMeshClass * new_mesh = NEW_REF(DynamicMeshClass,(pcount,vcount));
1132
1133 if (model->Get_Flag(MeshModelClass::SORT)) {
1134 new_mesh->Enable_Sort();
1135 }
1136 new_mesh->Set_Pass_Count(mtl_params.PassCount);
1137
1138 bool has_textures = false;
1139 for (ipass=0; ipass<model->Get_Pass_Count(); ipass++) {
1140 if (model->Peek_Single_Material(ipass) != NULL) {
1141 matinfo->Add_Vertex_Material(model->Peek_Single_Material(ipass));
1142 }
1143 for (int istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
1144 if (model->Peek_Single_Texture(ipass,istage) != NULL) {
1145 matinfo->Add_Texture(model->Peek_Single_Texture(ipass,istage));
1146 has_textures = true;
1147 }
1148 }
1149 }
1150 new_mesh->Set_Material_Info(matinfo);
1151
1152 for (ipass=0; ipass<model->Get_Pass_Count(); ipass++) {
1153 new_mesh->Set_Vertex_Material(model->Peek_Single_Material(ipass),false,ipass);
1154 new_mesh->Set_Shader(model->Get_Single_Shader(ipass),ipass);
1155
1156 for (istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
1157 TextureClass * tex = model->Peek_Single_Texture(ipass,istage);
1158 if (tex != NULL) {
1159 new_mesh->Peek_Model()->Set_Single_Texture(tex,ipass,istage);
1160 }
1161 }
1162 }
1163
1164 REF_PTR_RELEASE(matinfo);
1165
1166
1167 /*
1168 ** Add the polygons and vertices to the mesh, transform the vertices
1169 ** back into the original mesh's coordinate system as we do this
1170 */
1171 for (ipoly=0; ipoly<ClipPools[ipool].Count(); ipoly++) {
1172
1173 PolygonClass & poly = ClipPools[ipool][ipoly];
1174
1175 new_mesh->Begin_Tri_Fan();
1176 SHATTER_DEBUG_SAY(("Begin Tri Fan\n"));
1177
1178 for(ivert=0; ivert<poly.Get_Vertex_Count(); ivert++) {
1179
1180 Vector3 pos,norm;
1181 VertexClass & vert = poly[ivert];
1182
1183 Matrix3D::Transform_Vector(Mshatter_to_mesh,vert.Position,&pos);
1184 norm = vert.Normal;
1185
1186 SHATTER_DEBUG_SAY(("Begin Vertex:\n"));
1187 new_mesh->Begin_Vertex();
1188 SHATTER_DEBUG_SAY(("postion: %f %f %f\n",pos.X,pos.Y,pos.Z));
1189 new_mesh->Location_Inline(pos);
1190 new_mesh->Normal(norm);
1191
1192 for (ipass=0; ipass<mtl_params.PassCount; ipass++) {
1193
1194 unsigned mycolor=0;
1195
1196 /*
1197 ** If there were vertex colors for this pass in the original mesh, then
1198 ** copy the color out of the vertex into the new mesh.
1199 */
1200 if (mtl_params.DCG[ipass] != NULL) {
1201 SHATTER_DEBUG_SAY(("DCG: pass:%d: %f %f %f\n",ipass,vert.DCG[ipass].X,vert.DCG[ipass].Y,vert.DCG[ipass].Z));
1202 /* OLD CODE
1203 new_mesh->DCG(Vector3(vert.DCG[ipass].X,vert.DCG[ipass].Y,vert.DCG[ipass].Z),ipass);
1204 new_mesh->Alpha(vert.DCG[ipass].W,ipass);
1205 */
1206 mycolor=vert.DCG[ipass];
1207 }
1208
1209 // HY- Multiplying DIG with DCG as in meshmdlio
1210 if (mtl_params.DIG[ipass] != NULL) {
1211 SHATTER_DEBUG_SAY(("DIG: pass:%d: %f %f %f\n",ipass,vert.DIG[ipass].X,vert.DIG[ipass].Y,vert.DIG[ipass].Z));
1213 Vector4 dc=DX8Wrapper::Convert_Color(vert.DIG[ipass]);
1214 mc=Vector4(mc.X*dc.X,mc.Y*dc.Y,mc.Z*dc.Z,mc.W);
1215 mycolor=DX8Wrapper::Convert_Color(mc);
1216 }
1217
1218 new_mesh->Color(mycolor);
1219
1220 /*
1221 ** If there were UV coordinates in the original mesh for either stage,
1222 ** then copy the vertex's uv's into into the new mesh.
1223 */
1224// #pragma MESSAGE("HY- Naty, will dynamesh support multiple stages of UV?")
1225 for (istage=0; istage<MeshMatDescClass::MAX_TEX_STAGES; istage++) {
1226 if (mtl_params.UV[ipass][istage] != NULL) {
1227 SHATTER_DEBUG_SAY(("UV: pass:%d stage: %d: %f %f\n",ipass,istage,vert.TexCoord[ipass][istage].X,vert.TexCoord[ipass][istage].Y));
1228 new_mesh->UV(vert.TexCoord[ipass][istage],istage);
1229 }
1230 }
1231 }
1232
1233 new_mesh->End_Vertex();
1234
1235 }
1236 new_mesh->End_Tri_Fan();
1237 }
1238
1239 /*
1240 ** Offset all vertices so that the bounding box center is 0,0,0 and
1241 ** record that offset into the transform of the mesh
1242 */
1243 new_mesh->Set_Dirty_Bounds();
1244 Vector3 center = new_mesh->Get_Bounding_Box().Center;
1245
1246 new_mesh->Translate_Vertices(-center);
1247
1248 Matrix3D tm(1);// = mesh->Get_Transform();
1249 tm.Translate(center);
1250 Matrix3D::Multiply(tm,mesh->Get_Transform(),&tm);
1251 new_mesh->Set_Transform(tm);
1252
1253 /*
1254 ** We gave it good vertex normals so clear their dirty flag
1255 */
1256 new_mesh->Set_Dirty_Bounds();
1257 new_mesh->Set_Dirty_Planes();
1258 new_mesh->Clear_Dirty_Vertex_Normals();
1259
1260 /*
1261 ** Install it in the mesh fragment pool, transferring our reference
1262 ** to the fragment array...
1263 */
1264 MeshFragments.Add(new_mesh);
1265 }
1266 }
1267 REF_PTR_RELEASE(model);
1268}
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define W3DNEW
Definition always.h:109
Vector3 Center
Definition aabox.h:123
BSPClass * Get_Front_Child(void)
void Set_Plane_From_Transform(const Matrix3D &tm)
void Clip_Polygon(const PolygonClass &poly)
const PlaneClass & Get_Plane(void)
BSPClass * Front
BSPClass * Back
PlaneClass Plane
BSPClass(HTreeClass *tree, int bone_index, int &leaf_index)
BSPClass * Get_Back_Child(void)
static Vector4 Convert_Color(unsigned color)
Definition dx8wrapper.h:958
void UV(float u, float v, int uv_array_index=0)
Definition dynamesh.h:306
void Normal(float x, float y, float z)
Definition dynamesh.h:266
bool End_Vertex(void)
Definition dynamesh.cpp:440
void Color(float r, float g, float b, float a, int color_array_index=0)
Definition dynamesh.h:281
void Set_Dirty_Bounds(void)
Definition dynamesh.h:378
void Begin_Tri_Fan(void)
Definition dynamesh.h:241
virtual void Set_Material_Info(MaterialInfoClass *mat_info)
Definition dynamesh.h:153
void Clear_Dirty_Vertex_Normals(void)
Definition dynamesh.h:383
void Translate_Vertices(const Vector3 &offset)
Definition dynamesh.cpp:667
void Set_Pass_Count(int passes)
Definition dynamesh.h:175
void Location_Inline(float x, float y, float z)
Definition dynamesh.h:249
void End_Tri_Fan(void)
Definition dynamesh.h:345
DynamicMeshModel * Peek_Model(void)
Definition dynamesh.h:409
void Enable_Sort(void)
Definition dynamesh.h:387
void Begin_Vertex(void)
Definition dynamesh.h:244
int Set_Shader(const ShaderClass &shader, int pass=0)
Definition dynamesh.h:183
void Set_Dirty_Planes(void)
Definition dynamesh.h:380
int Set_Vertex_Material(int idx, int pass=0)
Definition dynamesh.cpp:681
void Set_Single_Texture(TextureClass *tex, int pass=0, int stage=0)
Definition dynamesh.h:89
int Get_Parent_Index(int bone_indx) const
Definition htree.cpp:968
void Base_Update(const Matrix3D &root)
Definition htree.cpp:531
WWINLINE int Num_Pivots(void) const
Definition htree.h:93
WWINLINE const Matrix3D & Get_Transform(int pivot) const
Definition htree.h:202
int Add_Vertex_Material(VertexMaterialClass *vmat)
Definition matinfo.h:226
int Add_Texture(TextureClass *tex)
Definition matinfo.cpp:74
static void Multiply(const Matrix3D &A, const Matrix3D &B, Matrix3D *set_result)
Definition matrix3d.cpp:640
WWINLINE Vector3 Get_Z_Vector() const
Definition matrix3d.h:308
void Translate(float x, float y, float z)
Definition matrix3d.h:670
void Get_Orthogonal_Inverse(Matrix3D &set_inverse) const
Definition matrix3d.cpp:570
static WWINLINE void Transform_Vector(const Matrix3D &tm, const Vector3 &in, Vector3 *out)
Definition matrix3d.h:1742
WWINLINE Vector3 Get_Translation(void) const
Definition matrix3d.h:217
WWINLINE void Scale(float scale)
Definition matrix3d.h:975
void Look_At(const Vector3 &p, const Vector3 &t, float roll)
Definition matrix3d.cpp:354
MeshModelClass * Get_Model(void)
Definition mesh.cpp:419
void Get_Bounding_Sphere(SphereClass *set_sphere)
const Vector3 * Get_Vertex_Normal_Array(void)
int Get_Vertex_Count(void) const
const char * Get_Name(void) const
const TriIndex * Get_Polygon_Array(void)
Vector3 * Get_Vertex_Array(void)
int Get_Polygon_Count(void) const
int Get_Flag(FlagsType flag)
bool Has_Shader_Array(int pass) const
Definition meshmdl.h:207
unsigned * Get_DCG_Array(int pass)
Definition meshmdl.h:180
bool Has_Material_Array(int pass) const
Definition meshmdl.h:206
int Get_Pass_Count(void) const
Definition meshmdl.h:174
bool Has_Texture_Array(int pass, int stage) const
Definition meshmdl.h:208
const Vector2 * Get_UV_Array(int pass=0, int stage=0)
Definition meshmdl.h:176
VertexMaterialClass * Peek_Single_Material(int pass=0) const
Definition meshmdl.h:198
unsigned * Get_DIG_Array(int pass)
Definition meshmdl.h:181
ShaderClass Get_Single_Shader(int pass=0) const
Definition meshmdl.h:194
TextureClass * Peek_Single_Texture(int pass=0, int stage=0) const
Definition meshmdl.h:199
unsigned * DCG[MeshMatDescClass::MAX_PASSES]
Vector2 * UV[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES]
unsigned * DIG[MeshMatDescClass::MAX_PASSES]
MeshMtlParamsClass(MeshModelClass *model)
Vector3 N
Definition plane.h:67
bool Compute_Intersection(const Vector3 &p0, const Vector3 &p1, float *set_t) const
Definition plane.h:156
float D
Definition plane.h:68
void Split(const PlaneClass &plane, PolygonClass &front, PolygonClass &back) const
const PlaneClass & Get_Plane(void) const
const VertexClass & operator[](int i) const
void Set_Plane(const PlaneClass &plane)
int Get_Material_ID(void) const
void Compute_Plane(void)
VertexClass Verts[BPT_POLY_MAX_VERTS]
PolygonClass & operator=(const PolygonClass &that)
int Get_Vertex_Count(void) const
void Set_Vertex_Count(int count)
bool Salvage_Degenerate(void)
bool Is_Degenerate(void)
void Set_Material_Id(int id)
int Which_Side(const PlaneClass &plane) const
PlaneClass Plane
virtual void Set_Transform(const Matrix3D &m)
Definition rendobj.cpp:423
virtual const AABoxClass & Get_Bounding_Box(void) const
Definition rendobj.h:575
const Matrix3D & Get_Transform(void) const
Definition rendobj.h:617
static void Reset_Clip_Pools(void)
static void Shutdown(void)
static RenderObjClass * Get_Fragment(int fragment_index)
static RenderObjClass * Peek_Fragment(int fragment_index)
static void Shatter_Mesh(MeshClass *mesh, const Vector3 &point, const Vector3 &velocity)
static void Release_Fragments(void)
static void Process_Clip_Pools(const Matrix3D &Mshatter_to_mesh, MeshClass *mesh, MeshMtlParamsClass &mtl_params)
static void Init(void)
static int Get_Fragment_Count(void)
float Radius
Definition sphere.h:91
int _cdecl Format(const TCHAR *format,...)
Definition wwstring.cpp:273
float Y
Definition vector2.h:79
static void Lerp(const Vector2 &a, const Vector2 &b, float t, Vector2 *set_result)
Definition vector2.h:662
float X
Definition vector2.h:74
static WWINLINE float Dot_Product(const Vector3 &a, const Vector3 &b)
Definition vector3.h:293
float X
Definition vector3.h:90
float Z
Definition vector3.h:92
float Y
Definition vector3.h:91
void Normalize(void)
Definition vector3.h:417
static void Lerp(const Vector3 &a, const Vector3 &b, float alpha, Vector3 *set_result)
Definition vector3.h:535
float Y
Definition vector4.h:67
float Z
Definition vector4.h:68
float X
Definition vector4.h:66
float W
Definition vector4.h:69
static Vector4 Lerp(const Vector4 &a, const Vector4 &b, float alpha)
Definition vector4.h:372
static void Transform(Vector3 *dst, const Vector3 *src, const Matrix3D &matrix, const int count)
Definition vp.cpp:80
int Which_Side(const PlaneClass &plane) const
static void Lerp(const VertexClass &v0, const VertexClass &v1, float lerp, VertexClass *res)
VertexClass & operator=(const VertexClass &that)
unsigned DCG[MeshMatDescClass::MAX_PASSES]
static void Intersect_Plane(const VertexClass &v0, const VertexClass &v1, const PlaneClass &plane, VertexClass *res)
unsigned DIG[MeshMatDescClass::MAX_PASSES]
Vector2 TexCoord[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES]
static WW3DAssetManager * Get_Instance(void)
Definition assetmgr.h:205
virtual HTreeClass * Get_HTree(const char *name)
static float Sqrt(float val)
Definition wwmath.h:568
Vector3i16 TriIndex
else return(RetVal)
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
#define NEW_REF(C, P)
Definition refcount.h:62
#define BPT_FRONT
#define BPT_COINCIDENCE_EPSILON
#define BPT_BACK
#define BPT_EPSILON
#define SHATTER_PATTERN_FORMAT
#define SHATTER_DEBUG_SAY(x)
#define BPT_BOTH
@ MAX_MESH_FRAGMENTS
#define BPT_ON
#define WWASSERT_PRINT(expr, string)
Definition wwdebug.h:135
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114