Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
decalmsh.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 : WW3D *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/decalmsh.cpp $*
26 * *
27 * Original Author:: Greg Hjelstrom *
28 * *
29 * $Author:: Kenny Mitchell *
30 * *
31 * $Modtime:: 06/26/02 4:04p $*
32 * *
33 * $Revision:: 24 $*
34 * *
35 * 06/26/02 KM Matrix name change to avoid MAX conflicts *
36 *---------------------------------------------------------------------------------------------*
37 * Functions: *
38 * DecalMeshClass::DecalMeshClass -- Constructor *
39 * DecalMeshClass::~DecalMeshClass -- Destructor *
40 * RigidDecalMeshClass::RigidDecalMeshClass -- Constructor *
41 * RigidDecalMeshClass::~RigidDecalMeshClass -- Destructor *
42 * RigidDecalMeshClass::Render -- Render the decals *
43 * RigidDecalMeshClass::Process_Material_Run -- scans the mesh for material runs *
44 * RigidDecalMeshClass::Create_Decal -- Generate a new decal *
45 * RigidDecalMeshClass::Delete_Decal -- Delete a decal *
46 * SkinDecalMeshClass::SkinDecalMeshClass -- Constructor *
47 * SkinDecalMeshClass::~SkinDecalMeshClass -- Destructor *
48 * SkinDecalMeshClass::Render -- Render the decals *
49 * SkinDecalMeshClass::Create_Decal -- Generate a new decal *
50 * SkinDecalMeshClass::Delete_Decal -- Delete a decal *
51 * SkinDecalMeshClass::Process_Material_Run -- scans the mesh for material runs *
52 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
53
54#include "decalmsh.h"
55#include "decalsys.h"
56#include "rinfo.h"
57#include "mesh.h"
58#include "meshmdl.h"
59#include "plane.h"
60#include "statistics.h"
61#include "dx8vertexbuffer.h"
62#include "dx8indexbuffer.h"
63#include "simplevec.h"
64#include "texture.h"
65#include "dx8wrapper.h"
66#include "dx8caps.h"
67
68#define DISABLE_CLIPPING 0
69
85{
86public:
87 void Reset(void);
88 void Add_Vertex(const Vector3 & point,const Vector3 & normal);
89 void Clip(const PlaneClass & plane,DecalPolyClass & dest) const;
90
93};
94
95
97{
98 Verts.Delete_All(false);
99 VertNorms.Delete_All(false);
100}
101
102void DecalPolyClass::Add_Vertex(const Vector3 & point,const Vector3 & norm)
103{
104 Verts.Add(point);
105 VertNorms.Add(norm);
106}
107
108void DecalPolyClass::Clip(const PlaneClass & plane,DecalPolyClass & dest) const
109{
110 dest.Reset();
111
112 if (Verts.Count() <= 2) return;
113
114 // temporary variables used in clipping
115 int i = 0;
116 int iprev = Verts.Count() - 1;
117 bool cur_point_in_front;
118 bool prev_point_in_front;
119
120 float alpha;
121 Vector3 int_point;
122 Vector3 int_normal;
123
124 // perform clipping
125 prev_point_in_front = plane.In_Front(Verts[iprev]);
126#if DISABLE_CLIPPING
127 prev_point_in_front = true;
128#endif
129
130 for (int j=0; j<Verts.Count(); j++) {
131
132 cur_point_in_front = plane.In_Front(Verts[i]);
133#if DISABLE_CLIPPING
134 cur_point_in_front = true;
135#endif
136
137 if (prev_point_in_front) {
138
139 if (cur_point_in_front) {
140
141 // Previous vertex was in front of plane and this vertex is in
142 // front of the plane so we emit this vertex.
143 dest.Add_Vertex(Verts[i],VertNorms[i]);
144
145 } else {
146
147 // Previous vert was in front, this vert is behind, compute
148 // the intersection and emit the point.
149 plane.Compute_Intersection(Verts[iprev],Verts[i],&alpha);
150 Vector3::Lerp(Verts[iprev],Verts[i],alpha,&int_point);
151 Vector3::Lerp(VertNorms[iprev],VertNorms[i],alpha,&int_normal);
152 dest.Add_Vertex(int_point,int_normal);
153
154 }
155
156 } else {
157
158 if (cur_point_in_front) {
159
160 // segment is going from the back halfspace to the front halfspace
161 // compute the intersection and emit it, then continue
162 // the edge into the front halfspace and emit the end point.
163 plane.Compute_Intersection(Verts[iprev],Verts[i],&alpha);
164 Vector3::Lerp(Verts[iprev],Verts[i],alpha,&int_point);
165 Vector3::Lerp(VertNorms[iprev],VertNorms[i],alpha,&int_normal);
166 dest.Add_Vertex(int_point,int_normal);
167 dest.Add_Vertex(Verts[i],VertNorms[i]);
168
169 }
170 }
171
172 prev_point_in_front = cur_point_in_front;
173 iprev = i;
174 i = (i+1)%(Verts.Count());
175 }
176}
177
178static DecalPolyClass _DecalPoly0;
179static DecalPolyClass _DecalPoly1;
180
181
182/*
183** DecalMeshClass Implementation
184*/
185
186/***********************************************************************************************
187 * DecalMeshClass::DecalMeshClass -- Constructor *
188 * *
189 * INPUT: *
190 * *
191 * OUTPUT: *
192 * *
193 * WARNINGS: *
194 * *
195 * HISTORY: *
196 * 1/26/00 gth : Created. *
197 *=============================================================================================*/
199 Parent(parent),
200 DecalSystem(system)
201{
202 WWASSERT(Parent != NULL);
204}
205
206
207/***********************************************************************************************
208 * DecalMeshClass::~DecalMeshClass -- Destructor *
209 * *
210 * INPUT: *
211 * *
212 * OUTPUT: *
213 * *
214 * WARNINGS: *
215 * *
216 * HISTORY: *
217 * 1/26/00 gth : Created. *
218 *=============================================================================================*/
222
223
224/*
225** RigidDecalMeshClass Implementation
226*/
227
228
229/***********************************************************************************************
230 * RigidDecalMeshClass::RigidDecalMeshClass -- Constructor *
231 * *
232 * INPUT: *
233 * *
234 * OUTPUT: *
235 * *
236 * WARNINGS: *
237 * *
238 * HISTORY: *
239 * 1/31/00 NH : Created. *
240 *=============================================================================================*/
242 DecalMeshClass(parent, system)
243{
244}
245
246
247/***********************************************************************************************
248 * RigidDecalMeshClass::~RigidDecalMeshClass -- Destructor *
249 * *
250 * INPUT: *
251 * *
252 * OUTPUT: *
253 * *
254 * WARNINGS: *
255 * *
256 * HISTORY: *
257 * 1/31/00 NH : Created. *
258 *=============================================================================================*/
260{
261 int i;
262
263 // Notify the system that this decal mesh is being destroyed.
264 for (i=0; i<Decals.Count(); i++) {
265 DecalSystem->Decal_Mesh_Destroyed(Decals[i].DecalID,this);
266 }
267
268 // Release all of our references. The memory in the arrays will automatically be
269 // released by the SimpleDynVecClass...
270 for (i=0; i<Polys.Count(); i++) {
272 }
273
274 for (i=0; i<Verts.Count(); i++) {
276 }
277}
278
279
280/***********************************************************************************************
281 * RigidDecalMeshClass::Render -- Render the decals *
282 * *
283 * INPUT: *
284 * *
285 * OUTPUT: *
286 * *
287 * WARNINGS: *
288 * *
289 * HISTORY: *
290 * 1/26/00 gth : Created. *
291 *=============================================================================================*/
293{
294 if ((Decals.Count() == 0) || (WW3D::Are_Decals_Enabled() == false)) return;
295
296 /*
297 ** Install the mesh'es transform. NOTE, this could go wrong if someone changes the
298 ** transform between the time that the mesh is rendered and the time that the decal
299 ** mesh is rendered... It shouldn't happen though.
300 */
301 DX8Wrapper::Set_Transform(D3DTS_WORLD,Parent->Get_Transform());
302
303 /*
304 ** Copy the vertices into the dynamic vb
305 */
307 {
308 DynamicVBAccessClass::WriteLockClass lock(&dynamic_vb);
310
311 for (int i=0; i<Verts.Count(); i++) {
312
313 vertex->x = Verts[i].X;
314 vertex->y = Verts[i].Y;
315 vertex->z = Verts[i].Z;
316
317 vertex->nx = VertNorms[i].X;
318 vertex->ny = VertNorms[i].Y;
319 vertex->nz = VertNorms[i].Z;
320
321 vertex->diffuse = 0xFFFFFFFF;
322
323 vertex->u1 = TexCoords[i].X;
324 vertex->v1 = TexCoords[i].Y;
325
326 vertex->u2 = 0.0f;
327 vertex->v2 = 0.0f;
328
329 vertex++;
330 }
331 }
332
333 /*
334 ** Copy the indices into the dynamic ib
335 */
336 DynamicIBAccessClass dynamic_ib(BUFFER_TYPE_DYNAMIC_DX8,Polys.Count() * 3);
337 {
338 DynamicIBAccessClass::WriteLockClass lock(&dynamic_ib);
339 unsigned short * indices = lock.Get_Index_Array();
340 for (int i=0; i < Polys.Count(); i++)
341 {
342 indices[i*3 + 0] = (unsigned short)Polys[i].I;
343 indices[i*3 + 1] = (unsigned short)Polys[i].J;
344 indices[i*3 + 2] = (unsigned short)Polys[i].K;
345 }
346 }
347
348 /*
349 ** Render in runs of constant material settings
350 */
351 int cur_poly_index = 0;
352 int next_poly_index = 0;
353
354 while (next_poly_index < Polys.Count()) {
355 next_poly_index = Process_Material_Run(cur_poly_index);
356
357 DX8Wrapper::Set_Index_Buffer(dynamic_ib,0);
359 DX8Wrapper::Draw_Triangles( 3*cur_poly_index,
360 (next_poly_index - cur_poly_index), // poly count
361 Polys[cur_poly_index].I,
362 1 + Polys[next_poly_index-1].K - Polys[cur_poly_index].I);
363 cur_poly_index = next_poly_index;
364 }
365
366}
367
368
369/***********************************************************************************************
370 * RigidDecalMeshClass::Process_Material_Run -- scans the mesh for material runs *
371 * *
372 * This function will install the materials for poly[start_index] and scan forward for *
373 * the next material change. It will return the start index for the next material change *
374 * *
375 * INPUT: *
376 * *
377 * OUTPUT: *
378 * *
379 * WARNINGS: *
380 * *
381 * HISTORY: *
382 * 2/22/2001 gth : Created. *
383 *=============================================================================================*/
385{
386 DX8Wrapper::Set_Texture(0,Textures[start_index]);
388 DX8Wrapper::Set_Shader(Shaders[start_index]);
389
390 int next_index = start_index;
391 while ( (next_index < Polys.Count()) &&
392 (Textures[next_index] == Textures[start_index]) &&
393 (Shaders[next_index] == Shaders[start_index]) &&
394 (VertexMaterials[next_index] == VertexMaterials[start_index]))
395 {
396 next_index++;
397 }
398 return next_index;
399}
400
401/***********************************************************************************************
402 * RigidDecalMeshClass::Create_Decal -- Generate a new decal *
403 * *
404 * INPUT: *
405 * *
406 * OUTPUT: *
407 * *
408 * WARNINGS: *
409 * All Decals on a mesh must be generated from the same DecalSystemClass! *
410 * *
411 * HISTORY: *
412 * 1/26/00 gth : Created. *
413 *=============================================================================================*/
415(
416 DecalGeneratorClass * generator,
417 const OBBoxClass & localbox,
419 const DynamicVectorClass<Vector3> * world_vertex_locs
420)
421{
422 // Since we can't rely on the hardware polygon offset function, I'm physically offsetting
423 // the decal polygons along the normal of the decal generator. If we could instead rely
424 // on hardware "polygon offset" we could remove this code and we could make decals non-sorting
425 Vector3 zbias_offset(0.0f,0.0f,0.0f);
426
427 if (!DX8Wrapper::Get_Current_Caps()->Support_ZBias()) {
428 const float ZBIAS_DISTANCE = 0.01f;
429 generator->Get_Transform().Get_Z_Vector(&zbias_offset);
430 Matrix3D invtm;
431 Parent->Get_Transform().Get_Orthogonal_Inverse(invtm);
432 Matrix3D::Rotate_Vector(invtm,zbias_offset,&zbias_offset);
433 zbias_offset *= ZBIAS_DISTANCE;
434 }
435
436 // NOTE: world_vertex_locs/norms should not be set for this class
437 WWASSERT(world_vertex_locs == 0);
438
439 int i,j;
440 WWASSERT(generator->Peek_Decal_System() == DecalSystem);
441
442 /*
443 ** If any polys were collected, add a new MeshDecalStruct
444 */
445 if (apt.Count() == 0) {
446 return false;
447 }
448
449 DecalStruct newdecal;
450 newdecal.DecalID = generator->Get_Decal_ID();
451 newdecal.FaceStartIndex = Polys.Count(); // start faces at the end of the current array
452 newdecal.FaceCount = 0; // init facecount to zero
453 newdecal.VertexStartIndex = Verts.Count(); // start vertices at the end of the current array
454 newdecal.VertexCount = 0; // init vertcount to zero
455
456 /*
457 ** Grab pointers to the parent mesh's components
458 */
459 MeshModelClass * model = Parent->Peek_Model();
460 const TriIndex * src_polys = model->Get_Polygon_Array();
461 const Vector3 * src_verts = model->Get_Vertex_Array();
462 const Vector3 * src_vnorms = model->Get_Vertex_Normal_Array();
463
464 /*
465 ** Grab a pointer to the material settings
466 */
467 MaterialPassClass * material = generator->Get_Material();
468
469 /*
470 ** Set up the generator for our coordinate system
471 */
472 generator->Set_Mesh_Transform(Parent->Get_Transform());
473
474 /*
475 ** Compute the clipping planes
476 */
477 PlaneClass planes[4];
478 Vector3 extent;
479
480 Matrix3x3::Rotate_Vector(localbox.Basis,Vector3(localbox.Extent.X,0,0),&extent);
481 Vector3 direction(localbox.Basis.Get_X_Vector());
482
483 planes[0].Set(-direction,localbox.Center + extent);
484 planes[1].Set(direction,localbox.Center - extent);
485
486 Matrix3x3::Rotate_Vector(localbox.Basis,Vector3(0,localbox.Extent.Y,0),&extent);
487 direction.Set(localbox.Basis.Get_Y_Vector());
488
489 planes[2].Set(-direction,localbox.Center + extent);
490 planes[3].Set(direction,localbox.Center - extent);
491
492 /*
493 ** Generate the faces and per-face info
494 */
495 bool added_polys = false;
496 Vector3 pdir = localbox.Basis.Get_Z_Vector();
497
498 for (i=0; i<apt.Count(); i++) {
499
500 /*
501 ** check if the polygon is backfacing
502 */
503 PlaneClass plane;
504 model->Compute_Plane(apt[i],&plane);
505
506 float dot = Vector3::Dot_Product(plane.N,pdir);
507 if (dot > generator->Get_Backface_Threshhold()) {
508 /*
509 ** Copy src_polys[apt[i]] into our clip polygon
510 */
511 _DecalPoly0.Reset();
512 const TriIndex & poly = src_polys[apt[i]];
513 for (j=0; j<3; j++) {
514 _DecalPoly0.Add_Vertex(src_verts[poly[j]] + zbias_offset,src_vnorms[poly[j]]);
515 }
516
517 /*
518 ** Clip against the edges of the bounding box
519 */
520 _DecalPoly0.Clip(planes[0],_DecalPoly1);
521 _DecalPoly1.Clip(planes[1],_DecalPoly0);
522 _DecalPoly0.Clip(planes[2],_DecalPoly1);
523 _DecalPoly1.Clip(planes[3],_DecalPoly0);
524
525 /*
526 ** Check if the clipped polygon is empty or degenerate
527 */
528 if (_DecalPoly0.Verts.Count() >= 3) {
529
530 /*
531 ** Extract triangles from the clipped polygon
532 */
533 int first_vert = Verts.Count();
534
535 for (j=1; j<_DecalPoly0.Verts.Count()-1; j++) {
536
537 /*
538 ** Check if this triangle is degenerate (Sutherland-Hodgeman can sometimes create degenerate tris)
539 */
540 // TODO
541
542 /*
543 ** Add the triangle, its plane equation, and the per-tri materials
544 */
545 added_polys = true;
546 Polys.Add(TriIndex(first_vert,first_vert + j,first_vert + j + 1));
547 Shaders.Add(material->Peek_Shader());
548 Textures.Add(material->Get_Texture()); // Get_Texture gives us a reference...
549 }
550
551 /*
552 ** Extract verts from the clipped polygon
553 */
554 for (j=0; j<_DecalPoly0.Verts.Count(); j++) {
555
556 Verts.Add(_DecalPoly0.Verts[j]);
557 _DecalPoly0.VertNorms[j].Normalize();
558 VertNorms.Add(_DecalPoly0.VertNorms[j]);
559 VertexMaterials.Add(material->Get_Material()); // Get_Material gives us a ref.
560
561 /*
562 ** Compute the uv coordinates for this vertex
563 */
564 Vector3 stq;
565 generator->Compute_Texture_Coordinate(Verts[Verts.Count()-1],&stq);
566 TexCoords.Add(Vector2(stq.X,stq.Y));
567 }
568 }
569 }
570 }
571
572 if (added_polys) {
573 newdecal.FaceCount = Polys.Count() - newdecal.FaceStartIndex;
574 newdecal.VertexCount = Verts.Count() - newdecal.VertexStartIndex;
575 Decals.Add(newdecal);
576
577 /*
578 ** tell the generator that we added a decal
579 */
580 generator->Add_Mesh(Parent);
581 }
582
583 material->Release_Ref();
584
585#ifdef WWDEBUG
586 /*
587 ** Some paranoid debug code: ensure all tris have valid vertex indices
588 */
589 int poly_count = Polys.Count();
590 int vert_count = Verts.Count();
591 for (int poly_idx = 0; poly_idx < poly_count; poly_idx++) {
592 WWASSERT (Polys[poly_idx].I < vert_count);
593 WWASSERT (Polys[poly_idx].I >= 0);
594 WWASSERT (Polys[poly_idx].J < vert_count);
595 WWASSERT (Polys[poly_idx].J >= 0);
596 WWASSERT (Polys[poly_idx].K < vert_count);
597 WWASSERT (Polys[poly_idx].K >= 0);
598 }
599#endif
600
601 /*
602 ** Only return true if we actually added a decal
603 */
604 return added_polys;
605}
606
607
608/***********************************************************************************************
609 * RigidDecalMeshClass::Delete_Decal -- Delete a decal *
610 * *
611 * INPUT: *
612 * *
613 * OUTPUT: *
614 * *
615 * WARNINGS: *
616 * *
617 * HISTORY: *
618 * 1/26/00 gth : Created. *
619 *=============================================================================================*/
621{
622 /*
623 ** Find the MeshDecal which matches the given id
624 */
625 int decal_index = -1;
626 for (int i = 0;i < Decals.Count(); i++) {
627 if (Decals[i].DecalID == id) {
628 decal_index = i;
629 break;
630 }
631 }
632
633 if (decal_index == -1) {
634 return false;
635 }
636
637 DecalStruct * decal = &Decals[decal_index];
638
639 /*
640 ** Remove all geometry used by this decal
641 */
642 Polys.Delete_Range(decal->FaceStartIndex,decal->FaceCount);
643 Verts.Delete_Range(decal->VertexStartIndex,decal->VertexCount);
644 VertNorms.Delete_Range(decal->VertexStartIndex,decal->VertexCount);
645 TexCoords.Delete_Range(decal->VertexStartIndex,decal->VertexCount);
646
647 /*
648 ** Re-index the remaining triangle vertex indices
649 */
650 for (int poly_index = 0; poly_index < Polys.Count(); poly_index++) {
651 if (Polys[poly_index].I > decal->VertexStartIndex) Polys[poly_index].I -= decal->VertexCount;
652 if (Polys[poly_index].J > decal->VertexStartIndex) Polys[poly_index].J -= decal->VertexCount;
653 if (Polys[poly_index].K > decal->VertexStartIndex) Polys[poly_index].K -= decal->VertexCount;
654 }
655
656 /*
657 ** Remove all materials used by this decal (remember to release refs!)
658 */
659 for (int fi=decal->FaceStartIndex; fi<decal->FaceCount; fi++) {
661 }
662 for (int vi=decal->VertexStartIndex; vi<decal->VertexCount; vi++) {
664 }
665 Shaders.Delete_Range(decal->FaceStartIndex,decal->FaceCount);
666 Textures.Delete_Range(decal->FaceStartIndex,decal->FaceCount);
667 VertexMaterials.Delete_Range(decal->VertexStartIndex,decal->VertexCount);
668
669 /*
670 ** Remove MeshDecal and refresh all other decal indices
671 */
672 for (int di=decal_index+1; di<Decals.Count(); di++) {
673 Decals[di].FaceStartIndex -= decal->FaceCount;
674 Decals[di].VertexStartIndex -= decal->VertexCount;
675 }
676 Decals.Delete(decal_index);
677
678#ifdef WWDEBUG
679 /*
680 ** Some paranoid debug code: ensure all tris have valid vertex indices
681 */
682 int poly_count = Polys.Count();
683 int vert_count = Verts.Count();
684 for (int poly_idx = 0; poly_idx < poly_count; poly_idx++) {
685 WWASSERT (Polys[poly_idx].I < vert_count);
686 WWASSERT (Polys[poly_idx].I >= 0);
687 WWASSERT (Polys[poly_idx].J < vert_count);
688 WWASSERT (Polys[poly_idx].J >= 0);
689 WWASSERT (Polys[poly_idx].K < vert_count);
690 WWASSERT (Polys[poly_idx].K >= 0);
691 }
692#endif
693
694 return true;
695}
696
697
698/*
699** Temporary Buffers
700** These buffers are used by the skin code for temporary storage of the deformed vertices and
701** vertex normals.
702*/
703static SimpleVecClass<Vector3> _TempVertexBuffer;
704static SimpleVecClass<Vector3> _TempNormalBuffer;
705
706
707/*
708** SkinDecalMeshClass Implementation
709*/
710
711
712/***********************************************************************************************
713 * SkinDecalMeshClass::SkinDecalMeshClass -- Constructor *
714 * *
715 * INPUT: *
716 * *
717 * OUTPUT: *
718 * *
719 * WARNINGS: *
720 * *
721 * HISTORY: *
722 * 1/31/00 NH : Created. *
723 *=============================================================================================*/
725 DecalMeshClass(parent, system)
726{
727}
728
729
730/***********************************************************************************************
731 * SkinDecalMeshClass::~SkinDecalMeshClass -- Destructor *
732 * *
733 * INPUT: *
734 * *
735 * OUTPUT: *
736 * *
737 * WARNINGS: *
738 * *
739 * HISTORY: *
740 * 1/31/00 NH : Created. *
741 *=============================================================================================*/
743{
744 int i;
745
746 // Notify the system that this decal mesh is being destroyed.
747 for (i=0; i<Decals.Count(); i++) {
748 DecalSystem->Decal_Mesh_Destroyed(Decals[i].DecalID,this);
749 }
750
751 // Release all of our references. The memory in the arrays will automatically be
752 // released by the SimpleDynVecClass...
753 for (i=0; i<Polys.Count(); i++) {
755 }
756
757 for (i=0; i<ParentVertexIndices.Count(); i++) {
759 }
760}
761
762
763/***********************************************************************************************
764 * SkinDecalMeshClass::Render -- Render the decals *
765 * *
766 * INPUT: *
767 * *
768 * OUTPUT: *
769 * *
770 * WARNINGS: *
771 * *
772 * HISTORY: *
773 * 1/31/00 NH : Created. *
774 *=============================================================================================*/
776{
777 if ((Decals.Count() == 0) || (WW3D::Are_Decals_Enabled() == false)) return;
778
779 /*
780 ** Don't allow decals on sorted meshes
781 */
782 MeshModelClass * model = Parent->Peek_Model();
783 if (model->Get_Flag(MeshModelClass::SORT)) {
784 WWDEBUG_SAY(("ERROR: decals applied to a sorted mesh!\n"));
785 return;
786 }
787
788 /*
789 ** Skin decals coordinates are in world space
790 */
792
793 /*
794 ** Skin decals have to get the deformed vertices of their parent meshes. For this
795 ** reason, decals on skins is not a very good idea...
796 */
797 _TempVertexBuffer.Uninitialised_Grow(model->Get_Vertex_Count());
798 _TempNormalBuffer.Uninitialised_Grow(model->Get_Vertex_Count());
799 Parent->Get_Deformed_Vertices(&(_TempVertexBuffer[0]),&(_TempNormalBuffer[0]));
800
801 /*
802 ** Copy the vertices into the dynamic vb
803 */
805 {
806 DynamicVBAccessClass::WriteLockClass lock(&dynamic_vb);
808
809 for (int i=0; i<ParentVertexIndices.Count(); i++) {
810 int src_i = ParentVertexIndices[i];
811 vertex->x = _TempVertexBuffer[src_i].X;
812 vertex->y = _TempVertexBuffer[src_i].Y;
813 vertex->z = _TempVertexBuffer[src_i].Z;
814
815 vertex->nx = _TempNormalBuffer[src_i].X;
816 vertex->ny = _TempNormalBuffer[src_i].Y;
817 vertex->nz = _TempNormalBuffer[src_i].Z;
818
819 vertex->diffuse = 0xFFFFFFFF;
820
821 vertex->u1 = TexCoords[i].X;
822 vertex->v1 = TexCoords[i].Y;
823
824 vertex->u2 = 0.0f;
825 vertex->v2 = 0.0f;
826
827 vertex++;
828 }
829 }
830
831 /*
832 ** Copy the indices into the dynamic ib
833 */
834 DynamicIBAccessClass dynamic_ib(BUFFER_TYPE_DYNAMIC_DX8,Polys.Count() * 3);
835 {
836 DynamicIBAccessClass::WriteLockClass lock(&dynamic_ib);
837 unsigned short * indices = lock.Get_Index_Array();
838 for (int i=0; i < Polys.Count(); i++)
839 {
840 indices[i*3 + 0] = (unsigned short)Polys[i].I;
841 indices[i*3 + 1] = (unsigned short)Polys[i].J;
842 indices[i*3 + 2] = (unsigned short)Polys[i].K;
843 }
844 }
845
846 /*
847 ** Render in runs of constant material settings
848 */
849 int cur_poly_index = 0;
850 int next_poly_index = 0;
851
852 while (next_poly_index < Polys.Count()) {
853 next_poly_index = Process_Material_Run(cur_poly_index);
854
855 DX8Wrapper::Set_Index_Buffer(dynamic_ib,0);
857 DX8Wrapper::Draw_Triangles(3*cur_poly_index,
858 (next_poly_index - cur_poly_index), // poly count
859 Polys[cur_poly_index].I,
860 1 + Polys[next_poly_index-1].K - Polys[cur_poly_index].I);
861
862 cur_poly_index = next_poly_index;
863 }
864}
865
866
867/***********************************************************************************************
868 * SkinDecalMeshClass::Process_Material_Run -- scans the mesh for material runs *
869 * *
870 * This function will install the materials for poly[start_index] and scan forward for *
871 * the next material change. It will return the start index for the next material change *
872 * *
873 * INPUT: *
874 * *
875 * OUTPUT: *
876 * *
877 * WARNINGS: *
878 * *
879 * HISTORY: *
880 * 2/22/2001 gth : Created. *
881 *=============================================================================================*/
883{
884 DX8Wrapper::Set_Texture(0,Textures[start_index]);
886 DX8Wrapper::Set_Shader(Shaders[start_index]);
887
888 int next_index = start_index;
889 while ( (next_index < Polys.Count()) &&
890 (Textures[next_index] == Textures[start_index]) &&
891 (Shaders[next_index] == Shaders[start_index]) &&
892 (VertexMaterials[next_index] == VertexMaterials[start_index]))
893 {
894 next_index++;
895 }
896 return next_index;
897}
898
899
900/***********************************************************************************************
901 * SkinDecalMeshClass::Create_Decal -- Generate a new decal *
902 * *
903 * INPUT: *
904 * *
905 * OUTPUT: *
906 * *
907 * WARNINGS: *
908 * All Decals on a mesh must be generated from the same DecalSystemClass! *
909 * *
910 * HISTORY: *
911 * 1/31/00 NH : Created. *
912 *=============================================================================================*/
914 const OBBoxClass & localbox, SimpleDynVecClass<uint32> & apt,
915 const DynamicVectorClass<Vector3> * world_vertex_locs)
916{
917 int i;
918 WWASSERT(generator->Peek_Decal_System() == DecalSystem);
919
920 // The dynamically updated vertex locations are needed - we have no static geometry
921 WWASSERT(world_vertex_locs);
922
923 /*
924 ** If any polys were collected, add a new MeshDecalStruct
925 */
926 if (apt.Count() == 0) {
927 return false;
928 }
929
930 DecalStruct newdecal;
931 newdecal.DecalID = generator->Get_Decal_ID();
932 newdecal.FaceStartIndex = Polys.Count(); // start faces at the end of the current array
933 newdecal.FaceCount = 0; // init facecount to zero
934 newdecal.VertexStartIndex = ParentVertexIndices.Count(); // start vertices at the end of the current array
935 newdecal.VertexCount = 0; // init vertcount to zero
936
937 /*
938 ** Grab pointers to the parent mesh's components
939 */
940 MeshModelClass * model = Parent->Peek_Model();
941 const TriIndex * src_polys = model->Get_Polygon_Array();
942
943 /*
944 ** Grab a pointer to the material settings
945 */
946 MaterialPassClass * material = generator->Get_Material();
947
948 /*
949 ** Set up the generator for the world coordinate system (the deformed vertices are in worldspace)
950 */
952
953 /*
954 ** Generate the faces and per-face info (remember to add-ref's)
955 ** TODO: rewrite this to take advantage of vertex sharing...
956 */
957 int face_size_hint = Polys.Count() + apt.Count();
958 int first_vert = ParentVertexIndices.Count();
959 for (i = 0; i < apt.Count(); i++) {
960 int offset = first_vert + i * 3;
961 Polys.Add(TriIndex(offset, offset + 1, offset + 2), face_size_hint);
962
963 Shaders.Add(material->Peek_Shader(), face_size_hint);
964 Textures.Add(material->Get_Texture(), face_size_hint); // Get_Texture gives us a reference...
965 }
966
967 /*
968 ** Copy the vertices and per-vertex info
969 ** TODO: rewrite this to take advantage of vertex sharing...
970 */
971 int vertex_size_hint = ParentVertexIndices.Count() + 3 * apt.Count();
972
973 for (i = 0; i < apt.Count(); i++) {
974 int face_index = apt[i];
975 for (int vi = 0; vi < 3; vi++) {
976
977 /*
978 ** Copy data for this vertex
979 */
980 ParentVertexIndices.Add(src_polys[face_index][vi], vertex_size_hint);
981 VertexMaterials.Add(material->Get_Material(), vertex_size_hint); // Get_Material gives us a ref.
982
983 /*
984 ** Compute the uv coordinates for this vertex
985 */
986 Vector3 stq;
987 generator->Compute_Texture_Coordinate((*world_vertex_locs)[ParentVertexIndices[ParentVertexIndices.Count() - 1]], &stq);
988 TexCoords.Add(Vector2(stq.X,stq.Y));
989
990 }
991 }
992
993 newdecal.FaceCount = Polys.Count() - newdecal.FaceStartIndex;
994 newdecal.VertexCount = ParentVertexIndices.Count() - newdecal.VertexStartIndex;
995 Decals.Add(newdecal);
996
997 material->Release_Ref();
998
999 /*
1000 ** tell the generator that we added a MeshDecal
1001 */
1002 generator->Add_Mesh(Parent);
1003
1004#ifdef WWDEBUG
1005 /*
1006 ** Some paranoid debug code: ensure all tris have valid vertex indices
1007 */
1008 int poly_count = Polys.Count();
1009 int vert_count = ParentVertexIndices.Count();
1010 for (int poly_idx = 0; poly_idx < poly_count; poly_idx++) {
1011 WWASSERT (Polys[poly_idx].I < vert_count);
1012 WWASSERT (Polys[poly_idx].I >= 0);
1013 WWASSERT (Polys[poly_idx].J < vert_count);
1014 WWASSERT (Polys[poly_idx].J >= 0);
1015 WWASSERT (Polys[poly_idx].K < vert_count);
1016 WWASSERT (Polys[poly_idx].K >= 0);
1017 }
1018#endif
1019
1020 // WWDEBUG_SAY(("Decal mesh now has: %d polys\r\n",Polys.Count()));
1021 return true;
1022}
1023
1024
1025/***********************************************************************************************
1026 * SkinDecalMeshClass::Delete_Decal -- Delete a decal *
1027 * *
1028 * INPUT: *
1029 * *
1030 * OUTPUT: *
1031 * *
1032 * WARNINGS: *
1033 * *
1034 * HISTORY: *
1035 * 1/31/00 NH : Created. *
1036 *=============================================================================================*/
1038{
1039 /*
1040 ** Find the MeshDecal which matches the given id
1041 */
1042 int decal_index = -1;
1043 for (int i = 0;i < Decals.Count(); i++) {
1044 if (Decals[i].DecalID == id) {
1045 decal_index = i;
1046 break;
1047 }
1048 }
1049
1050 if (decal_index == -1) {
1051 return false;
1052 }
1053
1054 DecalStruct * decal = &Decals[decal_index];
1055
1056 /*
1057 ** Remove all geometry used by this decal
1058 */
1059 Polys.Delete_Range(decal->FaceStartIndex, decal->FaceCount);
1060 ParentVertexIndices.Delete_Range(decal->VertexStartIndex, decal->VertexCount);
1061 TexCoords.Delete_Range(decal->VertexStartIndex, decal->VertexCount);
1062
1063 /*
1064 ** Re-index the remaining triangle vertex indices
1065 */
1066 for (int poly_index = 0; poly_index < Polys.Count(); poly_index++) {
1067 if (Polys[poly_index].I > decal->VertexStartIndex) Polys[poly_index].I -= decal->VertexCount;
1068 if (Polys[poly_index].J > decal->VertexStartIndex) Polys[poly_index].J -= decal->VertexCount;
1069 if (Polys[poly_index].K > decal->VertexStartIndex) Polys[poly_index].K -= decal->VertexCount;
1070 }
1071
1072 /*
1073 ** Remove all materials used by this decal (remember to release refs!)
1074 */
1075 for (int fi = decal->FaceStartIndex; fi < decal->FaceCount; fi++) {
1077 }
1078 for (int vi=decal->VertexStartIndex; vi<decal->VertexCount; vi++) {
1080 }
1081 Shaders.Delete_Range(decal->FaceStartIndex,decal->FaceCount);
1082 Textures.Delete_Range(decal->FaceStartIndex,decal->FaceCount);
1083 VertexMaterials.Delete_Range(decal->VertexStartIndex,decal->VertexCount);
1084
1085 /*
1086 ** Remove MeshDecal and refresh all other decal indices
1087 */
1088 for (int di=decal_index+1; di<Decals.Count(); di++) {
1089 Decals[di].FaceStartIndex -= decal->FaceCount;
1090 Decals[di].VertexStartIndex -= decal->VertexCount;
1091 }
1092 Decals.Delete(decal_index);
1093
1094#ifdef WWDEBUG
1095 /*
1096 ** Some paranoid debug code: ensure all tris have valid vertex indices
1097 */
1098 int poly_count = Polys.Count();
1099 int vert_count = ParentVertexIndices.Count();
1100 for (int poly_idx = 0; poly_idx < poly_count; poly_idx++) {
1101 WWASSERT (Polys[poly_idx].I < vert_count);
1102 WWASSERT (Polys[poly_idx].I >= 0);
1103 WWASSERT (Polys[poly_idx].J < vert_count);
1104 WWASSERT (Polys[poly_idx].J >= 0);
1105 WWASSERT (Polys[poly_idx].K < vert_count);
1106 WWASSERT (Polys[poly_idx].K >= 0);
1107 }
1108#endif
1109
1110 return true;
1111}
#define NULL
Definition BaseType.h:92
#define WWASSERT
unsigned long uint32
Definition bittype.h:46
static void Set_Vertex_Buffer(const VertexBufferClass *vb, unsigned stream=0)
static void Set_Texture(unsigned stage, TextureBaseClass *texture)
static const DX8Caps * Get_Current_Caps()
Definition dx8wrapper.h:536
static void Set_Index_Buffer(const IndexBufferClass *ib, unsigned short index_base_offset)
static void Draw_Triangles(unsigned buffer_type, unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, unsigned short vertex_count)
static void Set_Material(const VertexMaterialClass *material)
static void Set_Shader(const ShaderClass &shader)
static void Set_Transform(D3DTRANSFORMSTATETYPE transform, const Matrix4x4 &m)
void Add_Mesh(RenderObjClass *mesh)
Definition decalsys.cpp:219
void Set_Mesh_Transform(const Matrix3D &tm)
Definition decalsys.cpp:261
DecalSystemClass * Peek_Decal_System(void)
Definition decalsys.h:148
MaterialPassClass * Get_Material(void)
Definition decalsys.h:170
uint32 Get_Decal_ID(void)
Definition decalsys.h:147
float Get_Backface_Threshhold(void)
Definition decalsys.h:156
DecalSystemClass * DecalSystem
Definition decalmsh.h:114
MeshClass * Parent
Definition decalmsh.h:113
virtual ~DecalMeshClass(void)
Definition decalmsh.cpp:219
DecalMeshClass(MeshClass *parent, DecalSystemClass *system)
Definition decalmsh.cpp:198
SimpleDynVecClass< Vector3 > Verts
Definition decalmsh.cpp:91
SimpleDynVecClass< Vector3 > VertNorms
Definition decalmsh.cpp:92
void Reset(void)
Definition decalmsh.cpp:96
void Clip(const PlaneClass &plane, DecalPolyClass &dest) const
Definition decalmsh.cpp:108
void Add_Vertex(const Vector3 &point, const Vector3 &normal)
Definition decalmsh.cpp:102
VertexFormatXYZNDUV2 * Get_Formatted_Vertex_Array()
ShaderClass Peek_Shader(void) const
Definition matpass.h:97
VertexMaterialClass * Get_Material(void) const
Definition matpass.cpp:228
TextureClass * Get_Texture(int stage=0) const
Definition matpass.cpp:203
static const Matrix3D Identity
Definition matrix3d.h:372
Vector3 Rotate_Vector(const Vector3 &vect) const
Definition matrix3d.cpp:300
WWINLINE Vector3 Get_Z_Vector() const
Definition matrix3d.h:308
WWINLINE Vector3 Get_Y_Vector(void) const
Definition matrix3.h:642
WWINLINE Vector3 Get_Z_Vector(void) const
Definition matrix3.h:647
static WWINLINE void Rotate_Vector(const Matrix3x3 &tm, const Vector3 &in, Vector3 *out)
Definition matrix3.h:982
WWINLINE Vector3 Get_X_Vector(void) const
Definition matrix3.h:637
const Vector3 * Get_Vertex_Normal_Array(void)
int Get_Vertex_Count(void) const
void Compute_Plane(int pidx, PlaneClass *set_plane) const
const TriIndex * Get_Polygon_Array(void)
Vector3 * Get_Vertex_Array(void)
int Get_Flag(FlagsType flag)
Vector3 Extent
Definition obbox.h:114
Matrix3x3 Basis
Definition obbox.h:112
Vector3 Center
Definition obbox.h:113
Vector3 N
Definition plane.h:67
bool Compute_Intersection(const Vector3 &p0, const Vector3 &p1, float *set_t) const
Definition plane.h:156
bool In_Front(const Vector3 &point) const
Definition plane.h:183
void Set(float a, float b, float c, float d)
Definition plane.h:117
void Compute_Texture_Coordinate(const Vector3 &point, Vector3 *set_stq)
virtual const Matrix3D & Get_Transform(void) const
WWINLINE void Release_Ref(void) const
Definition refcount.h:146
virtual ~RigidDecalMeshClass(void)
Definition decalmsh.cpp:259
SimpleDynVecClass< Vector3 > Verts
Definition decalmsh.h:157
virtual bool Create_Decal(DecalGeneratorClass *generator, const OBBoxClass &localbox, SimpleDynVecClass< uint32 > &apt, const DynamicVectorClass< Vector3 > *world_vertex_locs=0)
Definition decalmsh.cpp:415
virtual void Render(void)
Definition decalmsh.cpp:292
SimpleDynVecClass< ShaderClass > Shaders
Definition decalmsh.h:163
SimpleDynVecClass< VertexMaterialClass * > VertexMaterials
Definition decalmsh.h:165
SimpleDynVecClass< TriIndex > Polys
Definition decalmsh.h:152
RigidDecalMeshClass(MeshClass *parent, DecalSystemClass *system)
Definition decalmsh.cpp:241
SimpleDynVecClass< DecalStruct > Decals
Definition decalmsh.h:180
SimpleDynVecClass< Vector2 > TexCoords
Definition decalmsh.h:166
SimpleDynVecClass< Vector3 > VertNorms
Definition decalmsh.h:158
virtual bool Delete_Decal(uint32 id)
Definition decalmsh.cpp:620
int Process_Material_Run(int start_index)
Definition decalmsh.cpp:384
SimpleDynVecClass< TextureClass * > Textures
Definition decalmsh.h:164
int Count(void) const
Definition simplevec.h:263
virtual ~SkinDecalMeshClass(void)
Definition decalmsh.cpp:742
SimpleDynVecClass< VertexMaterialClass * > VertexMaterials
Definition decalmsh.h:229
SimpleDynVecClass< ShaderClass > Shaders
Definition decalmsh.h:227
virtual bool Delete_Decal(uint32 id)
SimpleDynVecClass< uint32 > ParentVertexIndices
Definition decalmsh.h:222
SimpleDynVecClass< DecalStruct > Decals
Definition decalmsh.h:244
virtual void Render(void)
Definition decalmsh.cpp:775
SimpleDynVecClass< TextureClass * > Textures
Definition decalmsh.h:228
virtual bool Create_Decal(DecalGeneratorClass *generator, const OBBoxClass &localbox, SimpleDynVecClass< uint32 > &apt, const DynamicVectorClass< Vector3 > *world_vertex_locs)
Definition decalmsh.cpp:913
SimpleDynVecClass< Vector2 > TexCoords
Definition decalmsh.h:230
int Process_Material_Run(int start_index)
Definition decalmsh.cpp:882
SkinDecalMeshClass(MeshClass *parent, DecalSystemClass *system)
Definition decalmsh.cpp:724
SimpleDynVecClass< TriIndex > Polys
Definition decalmsh.h:217
static WWINLINE float Dot_Product(const Vector3 &a, const Vector3 &b)
Definition vector3.h:293
float X
Definition vector3.h:90
float Y
Definition vector3.h:91
WWINLINE void Set(float x, float y, float z)
Definition vector3.h:103
static void Lerp(const Vector3 &a, const Vector3 &b, float alpha, Vector3 *set_result)
Definition vector3.h:535
static bool Are_Decals_Enabled(void)
Definition ww3d.h:270
const unsigned dynamic_fvf_type
@ BUFFER_TYPE_DYNAMIC_DX8
Definition dx8wrapper.h:90
#define I(x, y, z)
Definition md5.cpp:89
Vector3i16 TriIndex
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114