Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
sortingrenderer.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/sortingrenderer.cpp $*
26 * *
27 * Original Author:: Greg Hjelstrom *
28 * *
29 * Author : Kenny Mitchell *
30 * *
31 * $Modtime:: 06/27/02 1:27p $*
32 * *
33 * $Revision:: 2 $*
34 * *
35 * 06/26/02 KM Matrix name change to avoid MAX conflicts *
36 * 06/27/02 KM Changes to max texture stage caps *
37 *---------------------------------------------------------------------------------------------*
38 * Functions: *
39 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
40
41#include "sortingrenderer.h"
42#include "dx8vertexbuffer.h"
43#include "dx8indexbuffer.h"
44#include "dx8wrapper.h"
45#include "vertmaterial.h"
46#include "texture.h"
47#include "d3d8.h"
48#include "D3dx8math.h"
49#include "statistics.h"
50#include <wwprofile.h>
51#include <algorithm>
52
53#ifdef _INTERNAL
54// for occasional debugging...
55// #pragma optimize("", off)
56// #pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
57#endif
58
59bool SortingRendererClass::_EnableTriangleDraw=true;
60static unsigned DEFAULT_SORTING_POLY_COUNT = 16384; // (count * 3) must be less than 65536
61static unsigned DEFAULT_SORTING_VERTEX_COUNT = 32768; // count must be less than 65536
62
64{
65 DEFAULT_SORTING_VERTEX_COUNT = val;
66 DEFAULT_SORTING_POLY_COUNT = val/2; //typically have 2:1 vertex:triangle ratio.
67}
68
70{
71 unsigned short i;
72 unsigned short j;
73 unsigned short k;
74};
75
77{
79 unsigned short idx;
80 float z;
81};
82
83bool operator <(const TempIndexStruct &l, const TempIndexStruct &r) { return l.z < r.z; }
84bool operator <=(const TempIndexStruct &l, const TempIndexStruct &r) { return l.z <= r.z; }
85bool operator >(const TempIndexStruct &l, const TempIndexStruct &r) { return l.z > r.z; }
86bool operator >=(const TempIndexStruct &l, const TempIndexStruct &r) { return l.z >= r.z; }
87bool operator ==(const TempIndexStruct &l, const TempIndexStruct &r) { return l.z == r.z; }
88// ----------------------------------------------------------------------------
89static
90void InsertionSort(TempIndexStruct *begin, TempIndexStruct *end)
91{
92 for (TempIndexStruct *iter = begin + 1; iter < end; ++iter) {
93 TempIndexStruct val = iter[0];
94 TempIndexStruct *insert = iter;
95 while (insert != begin && insert[-1] > val) {
96 insert[0] = insert[-1];
97 insert -= 1;
98 }
99 insert[0] = val;
100 }
101}
102
103// ----------------------------------------------------------------------------
104static
105void Sort(TempIndexStruct *begin, TempIndexStruct *end)
106{
107 const int diff = end - begin;
108 if (diff <= 16) {
109 // Insertion sort has less overhead for small arrays
110 InsertionSort(begin, end);
111 } else {
112 // Choose the median of begin, mid, and (end - 1) as the partitioning element.
113 // Rearrange so that *(begin + 1) <= *begin <= *(end - 1). These will be guard
114 // elements.
115 TempIndexStruct *mid = begin + diff/2;
116 std::swap(mid[0], begin[1]);
117 if (begin[1] > end[-1]) {
118 std::swap(begin[1], end[-1]);
119 }
120 if (begin[0] > end[-1]) {
121 std::swap(begin[0], end[-1]);
122 } // end[-1] has the largest element
123 if (begin[1] > begin[0]) {
124 std::swap(begin[1], begin[0]);
125 } // begin[0] has the middle element and begin[1] has the smallest element
126
127 // *begin is now the partitioning element
128 TempIndexStruct *begin1 = begin + 1; // TODO: Temp fix until I find out who is passing me NaN
129 TempIndexStruct *end1 = end - 1; // TODO: Temp fix until I find out who is passing me NaN
130 TempIndexStruct *left = begin + 1;
131 TempIndexStruct *right = end - 1;
132 for (;;) {
133#if 0 // TODO: Temp fix until I find out who is passing me NaN.
134 do ++left; while (left[0] < begin[0]); // Scan up to find element >= than partition
135 do --right; while (right[0] > begin[0]); // Scan down to find element <= than partition
136#else
137 do ++left; while (left < end1 && left[0] < begin[0]); // Scan up to find element >= than partition
138 do --right; while (right > begin1 && right[0] > begin[0]); // Scan down to find element <= than partition
139#endif
140 if (right < left) break; // Pointers crossed. Partitioning completed.
141 std::swap(left[0], right[0]); // Exchange elements.
142 }
143 std::swap(begin[0], right[0]); // Insert partition element
144
145 // Sort the smaller subarray first then the larger
146 if (right - begin > end - (right + 1)) {
147 Sort(right + 1, end);
148 Sort(begin, right);
149 } else {
150 Sort(begin, right);
151 Sort(right + 1, end);
152 }
153 }
154}
155
156// ----------------------------------------------------------------------------
157
158class SortingNodeStruct : public DLNodeClass<SortingNodeStruct>
159{
161
162public:
164
166
168 unsigned short start_index; // First index used in the ib
169 unsigned short polygon_count; // Polygon count to process (3 indices = one polygon)
170 unsigned short min_vertex_index; // First index used in the vb
171 unsigned short vertex_count; // Number of vertices used in vb
172};
173
174static DLListClass<SortingNodeStruct> sorted_list;
175static DLListClass<SortingNodeStruct> clean_list;
176static unsigned total_sorting_vertices;
177
178static SortingNodeStruct* Get_Sorting_Struct()
179{
180
181 SortingNodeStruct* state=clean_list.Head();
182 if (state) {
183 state->Remove();
184 return state;
185 }
187 return state;
188}
189
190// ----------------------------------------------------------------------------
191//
192// Temporary arrays for the sorting system
193//
194// ----------------------------------------------------------------------------
195
196static TempIndexStruct* temp_index_array;
197static unsigned temp_index_array_count;
198
199static TempIndexStruct* Get_Temp_Index_Array(unsigned count)
200{
201 if (count < DEFAULT_SORTING_POLY_COUNT)
202 count = DEFAULT_SORTING_POLY_COUNT;
203 if (count>temp_index_array_count) {
204 delete[] temp_index_array;
205 temp_index_array=W3DNEWARRAY TempIndexStruct[count];
206 temp_index_array_count=count;
207 }
208 return temp_index_array;
209}
210
211// ----------------------------------------------------------------------------
212//
213// Insert triangles to the sorting system.
214//
215// ----------------------------------------------------------------------------
216
218 const SphereClass& bounding_sphere,
219 unsigned short start_index,
220 unsigned short polygon_count,
221 unsigned short min_vertex_index,
222 unsigned short vertex_count)
223{
225 DX8Wrapper::Draw_Triangles(start_index,polygon_count,min_vertex_index,vertex_count);
226 return;
227 }
228
229 SNAPSHOT_SAY(("SortingRenderer::Insert(start_i: %d, polygons : %d, min_vi: %d, vertex_count: %d)\n",
230 start_index,polygon_count,min_vertex_index,vertex_count));
231
232
233 DX8_RECORD_SORTING_RENDER(polygon_count,vertex_count);
234
235 SortingNodeStruct* state=Get_Sorting_Struct();
236
238
239 WWASSERT(
242
243
244 state->bounding_sphere=bounding_sphere;
245 state->start_index=start_index;
246 state->polygon_count=polygon_count;
247 state->min_vertex_index=min_vertex_index;
248 state->vertex_count=vertex_count;
249
251 WWASSERT(vertex_buffer);
252 WWASSERT(state->vertex_count<=vertex_buffer->Get_Vertex_Count());
253
254 D3DXMATRIX mtx=(D3DXMATRIX&)state->sorting_state.world*(D3DXMATRIX&)state->sorting_state.view;
255 D3DXVECTOR3 vec=(D3DXVECTOR3&)state->bounding_sphere.Center;
256 D3DXVECTOR4 transformed_vec;
257 D3DXVec3Transform(
258 &transformed_vec,
259 &vec,
260 &mtx);
261 state->transformed_center=Vector3(transformed_vec[0],transformed_vec[1],transformed_vec[2]);
262
263
265
266 SortingNodeStruct* node=sorted_list.Head();
267 while (node) {
268 if (state->transformed_center.Z>node->transformed_center.Z) {
269 if (sorted_list.Head()==sorted_list.Tail())
270 sorted_list.Add_Head(state);
271 else
272 state->Insert_Before(node);
273 break;
274 }
275 node=node->Succ();
276 }
277 if (!node) sorted_list.Add_Tail(state);
278
279#ifdef WWDEBUG
280 unsigned short* indices=NULL;
282 WWASSERT(index_buffer);
283 indices=index_buffer->index_buffer;
284 WWASSERT(indices);
285 indices+=state->start_index;
286 indices+=state->sorting_state.iba_offset;
287
288 for (int i=0;i<state->polygon_count;++i) {
289 unsigned short idx1=indices[i*3]-state->min_vertex_index;
290 unsigned short idx2=indices[i*3+1]-state->min_vertex_index;
291 unsigned short idx3=indices[i*3+2]-state->min_vertex_index;
292 WWASSERT(idx1<state->vertex_count);
293 WWASSERT(idx2<state->vertex_count);
294 WWASSERT(idx3<state->vertex_count);
295 }
296#endif // WWDEBUG
297}
298
299// ----------------------------------------------------------------------------
300//
301// Insert triangles to the sorting system, with no bounding information.
302//
303// ----------------------------------------------------------------------------
304
306 unsigned short start_index,
307 unsigned short polygon_count,
308 unsigned short min_vertex_index,
309 unsigned short vertex_count)
310{
311 SphereClass sphere(Vector3(0.0f,0.0f,0.0f),0.0f);
312 Insert_Triangles(sphere,start_index,polygon_count,min_vertex_index,vertex_count);
313}
314
315// ----------------------------------------------------------------------------
316//
317// Flush all sorting polygons.
318//
319// ----------------------------------------------------------------------------
320
322{
323 int i;
324 for (i=0;i<MAX_VERTEX_STREAMS;++i) {
326 }
330 {
332 }
333}
334
335static unsigned overlapping_node_count;
336static unsigned overlapping_polygon_count;
337static unsigned overlapping_vertex_count;
338static const unsigned MAX_OVERLAPPING_NODES=4096;
339static SortingNodeStruct* overlapping_nodes[MAX_OVERLAPPING_NODES];
340
341// ----------------------------------------------------------------------------
342
343void SortingRendererClass::Insert_To_Sorting_Pool(SortingNodeStruct* state)
344{
345 if (overlapping_node_count>=MAX_OVERLAPPING_NODES) {
346 Release_Refs(state);
347 WWASSERT(0);
348 return;
349 }
350
351 overlapping_nodes[overlapping_node_count]=state;
352 overlapping_vertex_count+=state->vertex_count;
353 overlapping_polygon_count+=state->polygon_count;
354 overlapping_node_count++;
355}
356
357// ----------------------------------------------------------------------------
358//static unsigned prevLight = 0xffffffff;
359
360static void Apply_Render_State(RenderStateStruct& render_state)
361{
362
363
364
365 DX8Wrapper::Set_Shader(render_state.shader);
366
368
370 {
371 DX8Wrapper::Set_Texture(i,render_state.Textures[i]);
372 }
373
374 DX8Wrapper::_Set_DX8_Transform(D3DTS_WORLD,render_state.world);
375 DX8Wrapper::_Set_DX8_Transform(D3DTS_VIEW,render_state.view);
376
377
378
379 if (!render_state.material->Get_Lighting())
380 return;
381 //prevLight = render_state.lightsHash;
382
383 if (render_state.LightEnable[0])
384 {
385
386 DX8Wrapper::Set_DX8_Light(0,&render_state.Lights[0]);
387 if (render_state.LightEnable[1])
388 {
389 DX8Wrapper::Set_DX8_Light(1,&render_state.Lights[1]);
390 if (render_state.LightEnable[2])
391 {
392 DX8Wrapper::Set_DX8_Light(2,&render_state.Lights[2]);
393 if (render_state.LightEnable[3])
394 DX8Wrapper::Set_DX8_Light(3,&render_state.Lights[3]);
395 else
397 }
398 else
400 }
401 else
403 }
404 else
406
407
408}
409
410// ----------------------------------------------------------------------------
411
412void SortingRendererClass::Flush_Sorting_Pool()
413{
414 if (!overlapping_node_count) return;
415
416 SNAPSHOT_SAY(("SortingSystem - Flush \n"));
417
418 // Fill dynamic index buffer with sorting index buffer vertices
419 TempIndexStruct* tis=Get_Temp_Index_Array(overlapping_polygon_count);
420
421 unsigned vertexAllocCount = overlapping_vertex_count;
422 if (DynamicVBAccessClass::Get_Default_Vertex_Count() < DEFAULT_SORTING_VERTEX_COUNT)
423 vertexAllocCount = DEFAULT_SORTING_VERTEX_COUNT; //make sure that we force the DX8 dynamic vertex buffer to maximum size
424 if (overlapping_vertex_count > vertexAllocCount)
425 vertexAllocCount = overlapping_vertex_count;
426 WWASSERT(DEFAULT_SORTING_VERTEX_COUNT == 1 || vertexAllocCount <= DEFAULT_SORTING_VERTEX_COUNT);
427 DynamicVBAccessClass dyn_vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,vertexAllocCount/*overlapping_vertex_count*/);
428 {
429 DynamicVBAccessClass::WriteLockClass lock(&dyn_vb_access);
430 VertexFormatXYZNDUV2* dest_verts=(VertexFormatXYZNDUV2 *)lock.Get_Formatted_Vertex_Array();
431
432 unsigned polygon_array_offset=0;
433 unsigned vertex_array_offset=0;
434 for (unsigned node_id=0;node_id<overlapping_node_count;++node_id) {
435 SortingNodeStruct* state=overlapping_nodes[node_id];
436 VertexFormatXYZNDUV2* src_verts=NULL;
437 SortingVertexBufferClass* vertex_buffer=static_cast<SortingVertexBufferClass*>(state->sorting_state.vertex_buffers[0]);
438 WWASSERT(vertex_buffer);
439 src_verts=vertex_buffer->VertexBuffer;
440 WWASSERT(src_verts);
441 src_verts+=state->sorting_state.vba_offset;
442 src_verts+=state->sorting_state.index_base_offset;
443 src_verts+=state->min_vertex_index;
444
445 // If you have a crash in here and "dest_verts" points to illegal memory area,
446 // it is because D3D is in illegal state, and the only known cure is rebooting.
447 // This illegal state is usually caused by Quake3-engine powered games such as MOHAA.
448 memcpy(dest_verts, src_verts, sizeof(VertexFormatXYZNDUV2)*state->vertex_count);
449 dest_verts += state->vertex_count;
450
451 D3DXMATRIX d3d_mtx=(D3DXMATRIX&)state->sorting_state.world*(D3DXMATRIX&)state->sorting_state.view;
452 const Matrix4x4& mtx=(const Matrix4x4&)d3d_mtx;
453
454 unsigned short* indices=NULL;
455 SortingIndexBufferClass* index_buffer=static_cast<SortingIndexBufferClass*>(state->sorting_state.index_buffer);
456 WWASSERT(index_buffer);
457 indices=index_buffer->index_buffer;
458 WWASSERT(indices);
459 indices+=state->start_index;
460 indices+=state->sorting_state.iba_offset;
461
462 if (mtx[0][2] == 0.0f && mtx[1][2] == 0.0f && mtx[3][2] == 0.0f && mtx[2][2] == 1.0f) {
463 // The common case for particle systems.
464 for (int i=0;i<state->polygon_count;++i) {
465 unsigned short idx1=indices[i*3]-state->min_vertex_index;
466 unsigned short idx2=indices[i*3+1]-state->min_vertex_index;
467 unsigned short idx3=indices[i*3+2]-state->min_vertex_index;
468 WWASSERT(idx1<state->vertex_count);
469 WWASSERT(idx2<state->vertex_count);
470 WWASSERT(idx3<state->vertex_count);
471 const VertexFormatXYZNDUV2 *v1 = src_verts + idx1;
472 const VertexFormatXYZNDUV2 *v2 = src_verts + idx2;
473 const VertexFormatXYZNDUV2 *v3 = src_verts + idx3;
474 unsigned array_index=i+polygon_array_offset;
475 WWASSERT(array_index<overlapping_polygon_count);
476 TempIndexStruct *tis_ptr = tis + array_index;
477 tis_ptr->tri.i = idx1 + vertex_array_offset;
478 tis_ptr->tri.j = idx2 + vertex_array_offset;
479 tis_ptr->tri.k = idx3 + vertex_array_offset;
480 tis_ptr->idx = node_id;
481 tis_ptr->z = (v1->z + v2->z + v3->z)/3.0f;
482 DEBUG_ASSERTCRASH((! _isnan(tis_ptr->z) && _finite(tis_ptr->z)), ("Triangle has invalid center"));
483 }
484 } else {
485 for (int i=0;i<state->polygon_count;++i) {
486 unsigned short idx1=indices[i*3]-state->min_vertex_index;
487 unsigned short idx2=indices[i*3+1]-state->min_vertex_index;
488 unsigned short idx3=indices[i*3+2]-state->min_vertex_index;
489 WWASSERT(idx1<state->vertex_count);
490 WWASSERT(idx2<state->vertex_count);
491 WWASSERT(idx3<state->vertex_count);
492 const VertexFormatXYZNDUV2 *v1 = src_verts + idx1;
493 const VertexFormatXYZNDUV2 *v2 = src_verts + idx2;
494 const VertexFormatXYZNDUV2 *v3 = src_verts + idx3;
495 unsigned array_index=i+polygon_array_offset;
496 WWASSERT(array_index<overlapping_polygon_count);
497 TempIndexStruct *tis_ptr = tis + array_index;
498 tis_ptr->tri.i = idx1 + vertex_array_offset;
499 tis_ptr->tri.j = idx2 + vertex_array_offset;
500 tis_ptr->tri.k = idx3 + vertex_array_offset;
501 tis_ptr->idx = node_id;
502 tis_ptr->z = (mtx[0][2]*(v1->x + v2->x + v3->x) +
503 mtx[1][2]*(v1->y + v2->y + v3->y) +
504 mtx[2][2]*(v1->z + v2->z + v3->z))/3.0f + mtx[3][2];
505 DEBUG_ASSERTCRASH((! _isnan(tis_ptr->z) && _finite(tis_ptr->z)), ("Triangle has invalid center"));
506 }
507 }
508
509 state->min_vertex_index=vertex_array_offset;
510
511 polygon_array_offset+=state->polygon_count;
512 vertex_array_offset+=state->vertex_count;
513 }
514 }
515
516 Sort(tis, tis + overlapping_polygon_count);
517
518/* ///@todo: Add code to break up rendering into multiple index buffer fills to allow more than 65536/3 triangles. -MW
519 int total_overlapping_polygon_count = overlapping_polygon_count;
520 while ( > 0)
521 {
522 if ((total_overlapping_polygon_count*3) > 65535)
523 { //overflowed the index buffer, must break into multiple batches
524 overlapping_polygon_count = 65535/3;
525 }
526 else
527 overlapping_polygon_count = total_overlapping_polygon_count;
528
529 //insert rendering code here!!
530
531 total_overlapping_polygon_count -= overlapping_polygon_count;
532 }
533*/
534 unsigned polygonAllocCount = overlapping_polygon_count;
535 if ((unsigned)(DynamicIBAccessClass::Get_Default_Index_Count()/3) < DEFAULT_SORTING_POLY_COUNT)
536 polygonAllocCount = DEFAULT_SORTING_POLY_COUNT; //make sure that we force the DX8 index buffer to maximum size
537 if (overlapping_polygon_count > polygonAllocCount)
538 polygonAllocCount = overlapping_polygon_count;
539 WWASSERT(DEFAULT_SORTING_POLY_COUNT <= 1 || polygonAllocCount <= DEFAULT_SORTING_POLY_COUNT);
540
541 DynamicIBAccessClass dyn_ib_access(BUFFER_TYPE_DYNAMIC_DX8,polygonAllocCount*3);
542 {
543 DynamicIBAccessClass::WriteLockClass lock(&dyn_ib_access);
544 ShortVectorIStruct* sorted_polygon_index_array=(ShortVectorIStruct*)lock.Get_Index_Array();
545
546 try {
547 for (unsigned a=0;a<overlapping_polygon_count;++a) {
548 sorted_polygon_index_array[a]=tis[a].tri;
549 }
551 } catch(...) {
553 }
554 }
555
556 // Set index buffer and render!
557
558 DX8Wrapper::Set_Index_Buffer(dyn_ib_access,0); // Override with this buffer (do something to prevent need for this!)
559 DX8Wrapper::Set_Vertex_Buffer(dyn_vb_access); // Override with this buffer (do something to prevent need for this!)
560
562
563 unsigned count_to_render=1;
564 unsigned start_index=0;
565 unsigned node_id=tis[0].idx;
566 for (unsigned i=1;i<overlapping_polygon_count;++i) {
567 if (node_id!=tis[i].idx) {
568 SortingNodeStruct* state=overlapping_nodes[node_id];
569 Apply_Render_State(state->sorting_state);
570
572 start_index*3,
573 count_to_render,
574 state->min_vertex_index,
575 state->vertex_count);
576
577 count_to_render=0;
578 start_index=i;
579 node_id=tis[i].idx;
580 }
581 count_to_render++; //keep track of number of polygons of same kind
582 }
583
584 // Render any remaining polygons...
585 if (count_to_render) {
586 SortingNodeStruct* state=overlapping_nodes[node_id];
587 Apply_Render_State(state->sorting_state);
588
590 start_index*3,
591 count_to_render,
592 state->min_vertex_index,
593 state->vertex_count);
594 }
595
596 // Release all references and return nodes back to the clean list for the frame...
597 for (node_id=0;node_id<overlapping_node_count;++node_id) {
598 SortingNodeStruct* state=overlapping_nodes[node_id];
599 Release_Refs(state);
600 clean_list.Add_Head(state);
601 }
602 overlapping_node_count=0;
603 overlapping_polygon_count=0;
604 overlapping_vertex_count=0;
605
606 SNAPSHOT_SAY(("SortingSystem - Done flushing\n"));
607
608}
609
610// ----------------------------------------------------------------------------
611
613{
614 WWPROFILE("SortingRenderer::Flush");
615 Matrix4x4 old_view;
616 Matrix4x4 old_world;
617 DX8Wrapper::Get_Transform(D3DTS_VIEW,old_view);
618 DX8Wrapper::Get_Transform(D3DTS_WORLD,old_world);
619
620 while (SortingNodeStruct* state=sorted_list.Head()) {
621 state->Remove();
622
625 Insert_To_Sorting_Pool(state);
626 }
627 else {
631 Release_Refs(state);
632 clean_list.Add_Head(state);
633 }
634 }
635
637 DX8Wrapper::_Enable_Triangle_Draw(_EnableTriangleDraw);
638 Flush_Sorting_Pool();
640
643 total_sorting_vertices=0;
644
647
648
649 DX8Wrapper::Set_Transform(D3DTS_VIEW,old_view);
650 DX8Wrapper::Set_Transform(D3DTS_WORLD,old_world);
651
652}
653
654// ----------------------------------------------------------------------------
655
657{
658 SortingNodeStruct *head = NULL;
659
660 //
661 // Flush the sorted list
662 //
663 while ((head = sorted_list.Head ()) != NULL) {
664 sorted_list.Remove_Head ();
665 delete head;
666 }
667
668 //
669 // Flush the clean list
670 //
671 while ((head = clean_list.Head ()) != NULL) {
672 clean_list.Remove_Head ();
673 delete head;
674 }
675
676 delete[] temp_index_array;
677 temp_index_array=NULL;
678 temp_index_array_count=0;
679}
680
681
682// ----------------------------------------------------------------------------
683//
684// Insert a VolumeParticle triangle into the sorting system.
685//
686// ----------------------------------------------------------------------------
687
689 const SphereClass& bounding_sphere,
690 unsigned short start_index,
691 unsigned short polygon_count,
692 unsigned short min_vertex_index,
693 unsigned short vertex_count,
694 unsigned short layerCount)
695{
697 DX8Wrapper::Draw_Triangles(start_index,polygon_count,min_vertex_index,vertex_count);
698 return;
699 }
700
701 //FOR VOLUME_PARTICLE LOGIC:
702 // WE MUST MULTIPLY THE VERTCOUNT AND POLYCOUNT BY THE VOLUME_PARTICLE DEPTH
703 DX8_RECORD_SORTING_RENDER( polygon_count * layerCount,vertex_count * layerCount);//THIS IS VOLUME_PARTICLE SPECIFIC
704
705 SortingNodeStruct* state=Get_Sorting_Struct();
707
708 WWASSERT(
711
712 state->bounding_sphere=bounding_sphere;
713 state->start_index=start_index;
714 state->min_vertex_index=min_vertex_index;
715 state->polygon_count=polygon_count * layerCount;//THIS IS VOLUME_PARTICLE SPECIFIC
716 state->vertex_count=vertex_count * layerCount;//THIS IS VOLUME_PARTICLE SPECIFIC
717
719 WWASSERT(vertex_buffer);
720 WWASSERT(state->vertex_count<=vertex_buffer->Get_Vertex_Count());
721
722 // Transform the center point to view space for sorting
723
724 D3DXMATRIX mtx=(D3DXMATRIX&)state->sorting_state.world*(D3DXMATRIX&)state->sorting_state.view;
725 D3DXVECTOR3 vec=(D3DXVECTOR3&)state->bounding_sphere.Center;
726 D3DXVECTOR4 transformed_vec;
727 D3DXVec3Transform(
728 &transformed_vec,
729 &vec,
730 &mtx);
731 state->transformed_center=Vector3(transformed_vec[0],transformed_vec[1],transformed_vec[2]);
732
733
734 // BUT WHAT IS THE DEAL WITH THE VERTCOUNT AND POLYCOUNT BEING N BUT TRANSFORMED CENTER COUNT == 1
735
736 //THE TRANSFORMED CENTER[2] IS THE ZBUFFER DEPTH
737
739
740 SortingNodeStruct* node=sorted_list.Head();
741 while (node) {
742 if (state->transformed_center.Z>node->transformed_center.Z) {
743 if (sorted_list.Head()==sorted_list.Tail())
744 sorted_list.Add_Head(state);
745 else
746 state->Insert_Before(node);
747 break;
748 }
749 node=node->Succ();
750 }
751 if (!node) sorted_list.Add_Tail(state);
752}
#define NULL
Definition BaseType.h:92
#define DEBUG_ASSERTCRASH(c, m)
Definition Debug.h:193
#define DX8_RECORD_SORTING_RENDER(polys, verts)
Definition statistics.h:77
#define WWASSERT
#define W3DNEWARRAY
Definition always.h:110
#define W3DMPO_GLUE(ARGCLASS)
Definition always.h:120
#define W3DNEW
Definition always.h:109
void Add_Head(DLNodeClass< T > *node)
Definition dllist.h:156
void Remove()
Definition dllist.h:125
T * Succ()
Definition dllist.h:146
void Insert_Before(DLNodeClass< T > *n)
Definition dllist.h:99
int Get_Max_Textures_Per_Pass() const
Definition dx8caps.h:232
static void Set_Vertex_Buffer(const VertexBufferClass *vb, unsigned stream=0)
static void Set_Texture(unsigned stage, TextureBaseClass *texture)
static void _Enable_Triangle_Draw(bool enable)
Definition dx8wrapper.h:461
static const DX8Caps * Get_Current_Caps()
Definition dx8wrapper.h:536
static bool _Is_Triangle_Draw_Enabled()
Definition dx8wrapper.h:462
static void _Set_DX8_Transform(D3DTRANSFORMSTATETYPE transform, const Matrix4x4 &m)
Definition dx8wrapper.h:763
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_DX8_Light(int index, D3DLIGHT8 *light)
Definition dx8wrapper.h:857
static void Set_Shader(const ShaderClass &shader)
static void Get_Transform(D3DTRANSFORMSTATETYPE transform, Matrix4x4 &m)
static void Set_Transform(D3DTRANSFORMSTATETYPE transform, const Matrix4x4 &m)
static void Apply_Render_State_Changes()
static void Release_Render_State()
static void Get_Render_State(RenderStateStruct &state)
static void Set_Render_State(const RenderStateStruct &state)
static unsigned short Get_Default_Index_Count(void)
current size of dynamic index buffer
static void _Reset(bool frame_changed)
static unsigned short Get_Default_Vertex_Count(void)
current size of dynamic vertex buffer
static void _Reset(bool frame_changed)
unsigned short * index_buffer
unsigned short polygon_count
unsigned short start_index
SphereClass bounding_sphere
unsigned short min_vertex_index
unsigned short vertex_count
RenderStateStruct sorting_state
static void Insert_Triangles(const SphereClass &bounding_sphere, unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, unsigned short vertex_count)
static void Insert_VolumeParticle(const SphereClass &bounding_sphere, unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, unsigned short vertex_count, unsigned short layerCount)
static void SetMinVertexBufferSize(unsigned val)
Vector3 Center
Definition sphere.h:90
float Z
Definition vector3.h:92
unsigned short Get_Vertex_Count() const
bool Get_Lighting() const
static bool Is_Sorting_Enabled(void)
Definition ww3d.h:220
int IndexBufferExceptionFunc(void)
const unsigned dynamic_fvf_type
@ BUFFER_TYPE_DYNAMIC_DX8
Definition dx8wrapper.h:90
@ BUFFER_TYPE_SORTING
Definition dx8wrapper.h:89
@ BUFFER_TYPE_DYNAMIC_SORTING
Definition dx8wrapper.h:91
const unsigned MAX_VERTEX_STREAMS
Definition dx8wrapper.h:77
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
bool operator==(const TempIndexStruct &l, const TempIndexStruct &r)
bool operator>=(const TempIndexStruct &l, const TempIndexStruct &r)
bool operator>(const TempIndexStruct &l, const TempIndexStruct &r)
void Release_Refs(SortingNodeStruct *state)
bool operator<(const TempIndexStruct &l, const TempIndexStruct &r)
bool operator<=(const TempIndexStruct &l, const TempIndexStruct &r)
D3DLIGHT8 Lights[4]
Definition dx8wrapper.h:185
unsigned vertex_buffer_types[MAX_VERTEX_STREAMS]
Definition dx8wrapper.h:190
unsigned short index_base_offset
Definition dx8wrapper.h:197
unsigned short vba_offset
Definition dx8wrapper.h:192
unsigned short iba_offset
Definition dx8wrapper.h:194
IndexBufferClass * index_buffer
Definition dx8wrapper.h:196
TextureBaseClass * Textures[MAX_TEXTURE_STAGES]
Definition dx8wrapper.h:184
ShaderClass shader
Definition dx8wrapper.h:182
unsigned index_buffer_type
Definition dx8wrapper.h:191
VertexMaterialClass * material
Definition dx8wrapper.h:183
VertexBufferClass * vertex_buffers[MAX_VERTEX_STREAMS]
Definition dx8wrapper.h:195
unsigned short idx
ShortVectorIStruct tri
#define SNAPSHOT_SAY(x)
Definition ww3d.h:68
#define WWPROFILE(name)
Definition wwprofile.h:270