sortingrenderer.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. /*
  2. ** Command & Conquer Generals(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. #include "sortingrenderer.h"
  19. #include "dx8vertexbuffer.h"
  20. #include "dx8indexbuffer.h"
  21. #include "dx8wrapper.h"
  22. #include "vertmaterial.h"
  23. #include "texture.h"
  24. #include "d3d8.h"
  25. #include "D3dx8math.h"
  26. #include "statistics.h"
  27. bool SortingRendererClass::_EnableTriangleDraw=true;
  28. unsigned DEFAULT_SORTING_POLY_COUNT = 16384; // (count * 3) must be less than 65536
  29. unsigned DEFAULT_SORTING_VERTEX_COUNT = 32768; // count must be less than 65536
  30. void SortingRendererClass::SetMinVertexBufferSize( unsigned val )
  31. {
  32. DEFAULT_SORTING_VERTEX_COUNT = val;
  33. DEFAULT_SORTING_POLY_COUNT = val/2; //typically have 2:1 vertex:triangle ratio.
  34. }
  35. struct ShortVectorIStruct
  36. {
  37. unsigned short i;
  38. unsigned short j;
  39. unsigned short k;
  40. ShortVectorIStruct(unsigned short i_,unsigned short j_,unsigned short k_) : i(i_),j(j_),k(k_) {}
  41. ShortVectorIStruct() {}
  42. };
  43. struct TempIndexStruct
  44. {
  45. ShortVectorIStruct tri;
  46. unsigned short idx;
  47. TempIndexStruct() {}
  48. TempIndexStruct(const ShortVectorIStruct& tri_, unsigned short idx_)
  49. :
  50. tri(tri_),
  51. idx(idx_)
  52. {
  53. }
  54. };
  55. // ----------------------------------------------------------------------------
  56. //
  57. // InsertionSort (T* array, K *keys, int l, int r)
  58. // Performs insertion sort on array 'array' elements [l-r]. Uses values from array
  59. // 'keys' as sort keys.
  60. //
  61. // ----------------------------------------------------------------------------
  62. template <class T, class K>
  63. void InsertionSort (
  64. T* array, // array to sort
  65. K* keys, // sort keys
  66. int l, // first item
  67. int r) // last item
  68. {
  69. for (int i = l+1; i < r; i++) {
  70. K v=keys[i];
  71. T tv=array[i];
  72. int j=i;
  73. while (keys[j-1] > v) {
  74. keys[j]=keys[j-1];
  75. array[j]=array[j-1];
  76. j--;
  77. if (j == l) break;
  78. };
  79. keys[j]=v;
  80. array[j]=tv;
  81. }
  82. }
  83. // ----------------------------------------------------------------------------
  84. //
  85. // QuickSort (T* array, K* a, int l, int r)
  86. //
  87. // Performs quicksort on array 'array'. Uses values from array 'keys' as sort keys.
  88. //
  89. // Once the length of the array to be sorted is less than 8, the routine calls
  90. // InsertionSort() to perform the actual sorting work.
  91. //
  92. // ----------------------------------------------------------------------------
  93. template <class T, class K>
  94. void QuickSort (
  95. T* array, // array to sort
  96. K* keys, // sort keys
  97. int l, // first element
  98. int r) // last element
  99. {
  100. if (r-l <= 8) {
  101. InsertionSort(array,keys,l,r+1);
  102. return;
  103. }
  104. K t;
  105. K v=keys[r];
  106. T ttemp;
  107. int i=l-1;
  108. int j=r;
  109. do {
  110. do { i++; } while (i<r && keys[i]<v);
  111. do { j--; } while (j>0 && keys[j]>v);
  112. WWASSERT(j>=0);
  113. WWASSERT(i<=r);
  114. ttemp=array[i]; array[i]=array[j]; array[j]=ttemp;
  115. t=keys[i]; keys[i]=keys[j]; keys[j]=t;
  116. } while (j>i);
  117. array[j]=array[i];
  118. array[i]=array[r];
  119. array[r]=ttemp;
  120. keys[j]=keys[i];
  121. keys[i]=keys[r];
  122. keys[r]=t;
  123. if (i-1>l) QuickSort(array,keys,l,i-1);
  124. if (r>i+1) QuickSort(array,keys,i+1,r);
  125. }
  126. // ----------------------------------------------------------------------------
  127. //
  128. // Sorts and array. Uses values from array 'keys' as sort keys.
  129. //
  130. // ----------------------------------------------------------------------------
  131. template <class T, class K>
  132. void Sort (
  133. T* array, // array to sort
  134. K *keys, // sort keys
  135. int count) // array element count
  136. {
  137. bool do_insertion = false;
  138. if (count<=1) return; // only one element.. return..
  139. int c=0; // count number of rise pairs
  140. int i;
  141. for (i = 1; i < count; i++)
  142. if (keys[i] >= keys[i-1]) c++;
  143. if (c+1 == count) return; // array already sorted
  144. if (c<50) do_insertion=true; // array smaller than 50 should use insertion sort
  145. if (c<count/3) { // if array is not rising
  146. T tmp;
  147. K tval;
  148. for (i=0;i<count/2;i++) {
  149. int neg = count-1-i;
  150. tmp=array[i]; array[i]=array[neg]; array[neg]=tmp;
  151. tval=keys[i]; keys[i] = keys[neg]; keys[neg]=tval;
  152. }
  153. if (!c) return;
  154. do_insertion = true;
  155. }
  156. if (do_insertion) InsertionSort(array,keys,0,count);
  157. else QuickSort(array,keys,0,count-1); // quick sort
  158. }
  159. // ----------------------------------------------------------------------------
  160. class SortingNodeStruct : public DLNodeClass<SortingNodeStruct>
  161. {
  162. W3DMPO_GLUE(SortingNodeStruct)
  163. public:
  164. RenderStateStruct sorting_state;
  165. SphereClass bounding_sphere;
  166. Vector3 transformed_center;
  167. unsigned short start_index; // First index used in the ib
  168. unsigned short polygon_count; // Polygon count to process (3 indices = one polygon)
  169. unsigned short min_vertex_index; // First index used in the vb
  170. unsigned short vertex_count; // Number of vertices used in vb
  171. };
  172. static DLListClass<SortingNodeStruct> sorted_list;
  173. static DLListClass<SortingNodeStruct> clean_list;
  174. static unsigned total_sorting_vertices;
  175. static SortingNodeStruct* Get_Sorting_Struct()
  176. {
  177. SortingNodeStruct* state=clean_list.Head();
  178. if (state) {
  179. state->Remove();
  180. return state;
  181. }
  182. state=W3DNEW SortingNodeStruct();
  183. return state;
  184. }
  185. // ----------------------------------------------------------------------------
  186. //
  187. // Temporary arrays for the sorting system
  188. //
  189. // ----------------------------------------------------------------------------
  190. static float* vertex_z_array;
  191. static float* polygon_z_array;
  192. static unsigned * node_id_array;
  193. static unsigned * sorted_node_id_array;
  194. static ShortVectorIStruct* polygon_index_array;
  195. static unsigned vertex_z_array_count;
  196. static unsigned polygon_z_array_count;
  197. static unsigned node_id_array_count;
  198. static unsigned sorted_node_id_array_count;
  199. static unsigned polygon_index_array_count;
  200. TempIndexStruct* temp_index_array;
  201. unsigned temp_index_array_count;
  202. static TempIndexStruct* Get_Temp_Index_Array(unsigned count)
  203. {
  204. if (count < DEFAULT_SORTING_POLY_COUNT)
  205. count = DEFAULT_SORTING_POLY_COUNT;
  206. if (count>temp_index_array_count) {
  207. delete[] temp_index_array;
  208. temp_index_array=W3DNEWARRAY TempIndexStruct[count];
  209. temp_index_array_count=count;
  210. }
  211. return temp_index_array;
  212. }
  213. static float* Get_Vertex_Z_Array(unsigned count)
  214. {
  215. if (count < DEFAULT_SORTING_VERTEX_COUNT)
  216. count = DEFAULT_SORTING_VERTEX_COUNT;
  217. if (count>vertex_z_array_count) {
  218. delete[] vertex_z_array;
  219. vertex_z_array=W3DNEWARRAY float[count];
  220. vertex_z_array_count=count;
  221. }
  222. return vertex_z_array;
  223. }
  224. static float* Get_Polygon_Z_Array(unsigned count)
  225. {
  226. if (count < DEFAULT_SORTING_POLY_COUNT)
  227. count = DEFAULT_SORTING_POLY_COUNT;
  228. if (count>polygon_z_array_count) {
  229. delete[] polygon_z_array;
  230. polygon_z_array=W3DNEWARRAY float[count];
  231. polygon_z_array_count=count;
  232. }
  233. return polygon_z_array;
  234. }
  235. static unsigned * Get_Node_Id_Array(unsigned count)
  236. {
  237. if (count < DEFAULT_SORTING_POLY_COUNT)
  238. count = DEFAULT_SORTING_POLY_COUNT;
  239. if (count>node_id_array_count) {
  240. delete[] node_id_array;
  241. node_id_array=W3DNEWARRAY unsigned[count];
  242. node_id_array_count=count;
  243. }
  244. return node_id_array;
  245. }
  246. static unsigned * Get_Sorted_Node_Id_Array(unsigned count)
  247. {
  248. if (count < DEFAULT_SORTING_POLY_COUNT)
  249. count = DEFAULT_SORTING_POLY_COUNT;
  250. if (count>sorted_node_id_array_count) {
  251. delete[] sorted_node_id_array;
  252. sorted_node_id_array=W3DNEWARRAY unsigned[count];
  253. sorted_node_id_array_count=count;
  254. }
  255. return sorted_node_id_array;
  256. }
  257. static ShortVectorIStruct* Get_Polygon_Index_Array(unsigned count)
  258. {
  259. if (count < DEFAULT_SORTING_POLY_COUNT)
  260. count = DEFAULT_SORTING_POLY_COUNT;
  261. if (count>polygon_index_array_count) {
  262. delete[] polygon_index_array;
  263. polygon_index_array=W3DNEWARRAY ShortVectorIStruct[count];
  264. polygon_index_array_count=count;
  265. }
  266. return polygon_index_array;
  267. }
  268. // ----------------------------------------------------------------------------
  269. //
  270. // Insert triangles to the sorting system.
  271. //
  272. // ----------------------------------------------------------------------------
  273. void SortingRendererClass::Insert_Triangles(
  274. const SphereClass& bounding_sphere,
  275. unsigned short start_index,
  276. unsigned short polygon_count,
  277. unsigned short min_vertex_index,
  278. unsigned short vertex_count)
  279. {
  280. if (!WW3D::Is_Sorting_Enabled()) {
  281. DX8Wrapper::Draw_Triangles(start_index,polygon_count,min_vertex_index,vertex_count);
  282. return;
  283. }
  284. DX8_RECORD_SORTING_RENDER(polygon_count,vertex_count);
  285. SortingNodeStruct* state=Get_Sorting_Struct();
  286. DX8Wrapper::Get_Render_State(state->sorting_state);
  287. WWASSERT(
  288. ((state->sorting_state.index_buffer_type==BUFFER_TYPE_SORTING || state->sorting_state.index_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) &&
  289. (state->sorting_state.vertex_buffer_type==BUFFER_TYPE_SORTING || state->sorting_state.vertex_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING)));
  290. state->bounding_sphere=bounding_sphere;
  291. state->start_index=start_index;
  292. state->polygon_count=polygon_count;
  293. state->min_vertex_index=min_vertex_index;
  294. state->vertex_count=vertex_count;
  295. SortingVertexBufferClass* vertex_buffer=static_cast<SortingVertexBufferClass*>(state->sorting_state.vertex_buffer);
  296. WWASSERT(vertex_buffer);
  297. WWASSERT(state->vertex_count<=vertex_buffer->Get_Vertex_Count());
  298. D3DXMATRIX mtx=(D3DXMATRIX&)state->sorting_state.world*(D3DXMATRIX&)state->sorting_state.view;
  299. D3DXVECTOR3 vec=(D3DXVECTOR3&)state->bounding_sphere.Center;
  300. D3DXVECTOR4 transformed_vec;
  301. D3DXVec3Transform(
  302. &transformed_vec,
  303. &vec,
  304. &mtx);
  305. state->transformed_center=Vector3(transformed_vec[0],transformed_vec[1],transformed_vec[2]);
  306. /// @todo lorenzen sez use a bucket sort here... and stop copying so much data so many times
  307. SortingNodeStruct* node=sorted_list.Head();
  308. while (node) {
  309. if (state->transformed_center.Z>node->transformed_center.Z) {
  310. if (sorted_list.Head()==sorted_list.Tail())
  311. sorted_list.Add_Head(state);
  312. else
  313. state->Insert_Before(node);
  314. break;
  315. }
  316. node=node->Succ();
  317. }
  318. if (!node) sorted_list.Add_Tail(state);
  319. #ifdef WWDEBUG
  320. unsigned short* indices=NULL;
  321. SortingIndexBufferClass* index_buffer=static_cast<SortingIndexBufferClass*>(state->sorting_state.index_buffer);
  322. WWASSERT(index_buffer);
  323. indices=index_buffer->index_buffer;
  324. WWASSERT(indices);
  325. indices+=state->start_index;
  326. indices+=state->sorting_state.iba_offset;
  327. for (int i=0;i<state->polygon_count;++i) {
  328. unsigned short idx1=indices[i*3]-state->min_vertex_index;
  329. unsigned short idx2=indices[i*3+1]-state->min_vertex_index;
  330. unsigned short idx3=indices[i*3+2]-state->min_vertex_index;
  331. WWASSERT(idx1<state->vertex_count);
  332. WWASSERT(idx2<state->vertex_count);
  333. WWASSERT(idx3<state->vertex_count);
  334. }
  335. #endif
  336. }
  337. // ----------------------------------------------------------------------------
  338. //
  339. // Insert triangles to the sorting system, with no bounding information.
  340. //
  341. // ----------------------------------------------------------------------------
  342. void SortingRendererClass::Insert_Triangles(
  343. unsigned short start_index,
  344. unsigned short polygon_count,
  345. unsigned short min_vertex_index,
  346. unsigned short vertex_count)
  347. {
  348. SphereClass sphere(Vector3(0.0f,0.0f,0.0f),0.0f);
  349. Insert_Triangles(sphere,start_index,polygon_count,min_vertex_index,vertex_count);
  350. }
  351. // ----------------------------------------------------------------------------
  352. //
  353. // Flush all sorting polygons.
  354. //
  355. // ----------------------------------------------------------------------------
  356. void Release_Refs(SortingNodeStruct* state)
  357. {
  358. REF_PTR_RELEASE(state->sorting_state.vertex_buffer);
  359. REF_PTR_RELEASE(state->sorting_state.index_buffer);
  360. REF_PTR_RELEASE(state->sorting_state.material);
  361. for (unsigned i=0;i<MAX_TEXTURE_STAGES;++i) {
  362. REF_PTR_RELEASE(state->sorting_state.Textures[i]);
  363. }
  364. }
  365. static unsigned overlapping_node_count;
  366. static unsigned overlapping_polygon_count;
  367. static unsigned overlapping_vertex_count;
  368. const unsigned MAX_OVERLAPPING_NODES=4096;
  369. static SortingNodeStruct* overlapping_nodes[MAX_OVERLAPPING_NODES];
  370. // ----------------------------------------------------------------------------
  371. void SortingRendererClass::Insert_To_Sorting_Pool(SortingNodeStruct* state)
  372. {
  373. if (overlapping_node_count>=MAX_OVERLAPPING_NODES) {
  374. Release_Refs(state);
  375. WWASSERT(0);
  376. return;
  377. }
  378. overlapping_nodes[overlapping_node_count]=state;
  379. overlapping_vertex_count+=state->vertex_count;
  380. overlapping_polygon_count+=state->polygon_count;
  381. overlapping_node_count++;
  382. }
  383. // ----------------------------------------------------------------------------
  384. static void Apply_Render_State(RenderStateStruct& render_state)
  385. {
  386. /* state->sorting_state.shader.Apply();
  387. */
  388. DX8Wrapper::Set_Shader(render_state.shader);
  389. /* if (render_state.material) render_state.material->Apply();
  390. */
  391. DX8Wrapper::Set_Material(render_state.material);
  392. /* if (render_state.Textures[2]) render_state.Textures[2]->Apply();
  393. if (render_state.Textures[3]) render_state.Textures[3]->Apply();
  394. if (render_state.Textures[4]) render_state.Textures[4]->Apply();
  395. if (render_state.Textures[5]) render_state.Textures[5]->Apply();
  396. if (render_state.Textures[6]) render_state.Textures[6]->Apply();
  397. if (render_state.Textures[7]) render_state.Textures[7]->Apply();
  398. */
  399. for (unsigned i=0;i<MAX_TEXTURE_STAGES;++i) {
  400. DX8Wrapper::Set_Texture(i,render_state.Textures[i]);
  401. }
  402. DX8Wrapper::_Set_DX8_Transform(D3DTS_WORLD,render_state.world);
  403. DX8Wrapper::_Set_DX8_Transform(D3DTS_VIEW,render_state.view);
  404. if (!render_state.material->Get_Lighting())
  405. return; //no point changing lights if they are ignored.
  406. if (render_state.LightEnable[0]) {
  407. DX8Wrapper::Set_DX8_Light(0,&render_state.Lights[0]);
  408. if (render_state.LightEnable[1]) {
  409. DX8Wrapper::Set_DX8_Light(1,&render_state.Lights[1]);
  410. if (render_state.LightEnable[2]) {
  411. DX8Wrapper::Set_DX8_Light(2,&render_state.Lights[2]);
  412. if (render_state.LightEnable[3]) {
  413. DX8Wrapper::Set_DX8_Light(3,&render_state.Lights[3]);
  414. }
  415. else {
  416. DX8Wrapper::Set_DX8_Light(3,NULL);
  417. }
  418. }
  419. else {
  420. DX8Wrapper::Set_DX8_Light(2,NULL);
  421. }
  422. }
  423. else {
  424. DX8Wrapper::Set_DX8_Light(1,NULL);
  425. }
  426. }
  427. else {
  428. DX8Wrapper::Set_DX8_Light(0,NULL);
  429. }
  430. // Matrix4 mtx;
  431. // mtx=render_state.world.Transpose();
  432. // DX8Wrapper::Set_Transform(D3DTS_WORLD,mtx);
  433. // mtx=render_state.view.Transpose();
  434. // DX8Wrapper::Set_Transform(D3DTS_VIEW,mtx);
  435. }
  436. // ----------------------------------------------------------------------------
  437. void SortingRendererClass::Flush_Sorting_Pool()
  438. {
  439. if (!overlapping_node_count) return;
  440. SNAPSHOT_SAY(("SortingSystem - Flush \n"));
  441. unsigned node_id;
  442. // Fill dynamic index buffer with sorting index buffer vertices
  443. unsigned * node_id_array=Get_Node_Id_Array(overlapping_polygon_count);
  444. float* polygon_z_array=Get_Polygon_Z_Array(overlapping_polygon_count);
  445. ShortVectorIStruct* polygon_idx_array=(ShortVectorIStruct*)Get_Polygon_Index_Array(overlapping_polygon_count);
  446. unsigned vertexAllocCount = overlapping_vertex_count;
  447. if (DynamicVBAccessClass::Get_Default_Vertex_Count() < DEFAULT_SORTING_VERTEX_COUNT)
  448. vertexAllocCount = DEFAULT_SORTING_VERTEX_COUNT; //make sure that we force the DX8 dynamic vertex buffer to maximum size
  449. if (overlapping_vertex_count > vertexAllocCount)
  450. vertexAllocCount = overlapping_vertex_count;
  451. WWASSERT(DEFAULT_SORTING_VERTEX_COUNT == 1 || vertexAllocCount <= DEFAULT_SORTING_VERTEX_COUNT);
  452. DynamicVBAccessClass dyn_vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,vertexAllocCount/*overlapping_vertex_count*/);
  453. {
  454. DynamicVBAccessClass::WriteLockClass lock(&dyn_vb_access);
  455. VertexFormatXYZNDUV2* dest_verts=lock.Get_Formatted_Vertex_Array();
  456. unsigned polygon_array_offset=0;
  457. unsigned vertex_array_offset=0;
  458. for (node_id=0;node_id<overlapping_node_count;++node_id) {
  459. SortingNodeStruct* state=overlapping_nodes[node_id];
  460. float* vertex_z_array=Get_Vertex_Z_Array(state->vertex_count);
  461. VertexFormatXYZNDUV2* src_verts=NULL;
  462. SortingVertexBufferClass* vertex_buffer=static_cast<SortingVertexBufferClass*>(state->sorting_state.vertex_buffer);
  463. WWASSERT(vertex_buffer);
  464. src_verts=vertex_buffer->VertexBuffer;
  465. WWASSERT(src_verts);
  466. src_verts+=state->sorting_state.vba_offset;
  467. src_verts+=state->sorting_state.index_base_offset;
  468. src_verts+=state->min_vertex_index;
  469. D3DXMATRIX d3d_mtx=(D3DXMATRIX&)state->sorting_state.world*(D3DXMATRIX&)state->sorting_state.view;
  470. D3DXMatrixTranspose(&d3d_mtx,&d3d_mtx);
  471. const Matrix4& mtx=(const Matrix4&)d3d_mtx;
  472. for (unsigned i=0;i<state->vertex_count;++i,++src_verts) {
  473. vertex_z_array[i] = (mtx[2][0] * src_verts->x + mtx[2][1] * src_verts->y + mtx[2][2] * src_verts->z + mtx[2][3]);
  474. *dest_verts++=*src_verts;
  475. }
  476. unsigned short* indices=NULL;
  477. SortingIndexBufferClass* index_buffer=static_cast<SortingIndexBufferClass*>(state->sorting_state.index_buffer);
  478. WWASSERT(index_buffer);
  479. indices=index_buffer->index_buffer;
  480. WWASSERT(indices);
  481. indices+=state->start_index;
  482. indices+=state->sorting_state.iba_offset;
  483. for (i=0;i<state->polygon_count;++i) {
  484. unsigned short idx1=indices[i*3]-state->min_vertex_index;
  485. unsigned short idx2=indices[i*3+1]-state->min_vertex_index;
  486. unsigned short idx3=indices[i*3+2]-state->min_vertex_index;
  487. WWASSERT(idx1<state->vertex_count);
  488. WWASSERT(idx2<state->vertex_count);
  489. WWASSERT(idx3<state->vertex_count);
  490. float z1=vertex_z_array[idx1];
  491. float z2=vertex_z_array[idx2];
  492. float z3=vertex_z_array[idx3];
  493. float z=(z1+z2+z3)/3.0f;
  494. unsigned array_index=i+polygon_array_offset;
  495. WWASSERT(array_index<overlapping_polygon_count);
  496. polygon_z_array[array_index]=z;
  497. node_id_array[array_index]=node_id;
  498. polygon_idx_array[array_index]=ShortVectorIStruct(
  499. idx1+vertex_array_offset,
  500. idx2+vertex_array_offset,
  501. idx3+vertex_array_offset);
  502. }
  503. state->min_vertex_index=vertex_array_offset;
  504. polygon_array_offset+=state->polygon_count;
  505. vertex_array_offset+=state->vertex_count;
  506. }
  507. }
  508. TempIndexStruct* tis=Get_Temp_Index_Array(overlapping_polygon_count);
  509. for (unsigned a=0;a<overlapping_polygon_count;++a) {
  510. tis[a]=TempIndexStruct(polygon_idx_array[a],node_id_array[a]);
  511. }
  512. Sort<TempIndexStruct,float>(tis,polygon_z_array,overlapping_polygon_count);
  513. /* ///@todo: Add code to break up rendering into multiple index buffer fills to allow more than 65536/3 triangles. -MW
  514. int total_overlapping_polygon_count = overlapping_polygon_count;
  515. while ( > 0)
  516. {
  517. if ((total_overlapping_polygon_count*3) > 65535)
  518. { //overflowed the index buffer, must break into multiple batches
  519. overlapping_polygon_count = 65535/3;
  520. }
  521. else
  522. overlapping_polygon_count = total_overlapping_polygon_count;
  523. //insert rendering code here!!
  524. total_overlapping_polygon_count -= overlapping_polygon_count;
  525. }
  526. */
  527. unsigned polygonAllocCount = overlapping_polygon_count;
  528. if ((unsigned)(DynamicIBAccessClass::Get_Default_Index_Count()/3) < DEFAULT_SORTING_POLY_COUNT)
  529. polygonAllocCount = DEFAULT_SORTING_POLY_COUNT; //make sure that we force the DX8 index buffer to maximum size
  530. if (overlapping_polygon_count > polygonAllocCount)
  531. polygonAllocCount = overlapping_polygon_count;
  532. WWASSERT(DEFAULT_SORTING_POLY_COUNT <= 1 || polygonAllocCount <= DEFAULT_SORTING_POLY_COUNT);
  533. DynamicIBAccessClass dyn_ib_access(BUFFER_TYPE_DYNAMIC_DX8,polygonAllocCount*3);
  534. {
  535. DynamicIBAccessClass::WriteLockClass lock(&dyn_ib_access);
  536. ShortVectorIStruct* sorted_polygon_index_array=(ShortVectorIStruct*)lock.Get_Index_Array();
  537. for (a=0;a<overlapping_polygon_count;++a) {
  538. sorted_polygon_index_array[a]=tis[a].tri;
  539. }
  540. }
  541. // Set index buffer and render!
  542. DX8Wrapper::Set_Index_Buffer(dyn_ib_access,0); // Override with this buffer (do something to prevent need for this!)
  543. DX8Wrapper::Set_Vertex_Buffer(dyn_vb_access); // Override with this buffer (do something to prevent need for this!)
  544. DX8Wrapper::Apply_Render_State_Changes();
  545. unsigned count_to_render=1;
  546. unsigned start_index=0;
  547. node_id=tis[0].idx;
  548. for (unsigned i=1;i<overlapping_polygon_count;++i) {
  549. if (node_id!=tis[i].idx) {
  550. SortingNodeStruct* state=overlapping_nodes[node_id];
  551. Apply_Render_State(state->sorting_state);
  552. DX8Wrapper::Draw_Triangles(
  553. start_index*3,
  554. count_to_render,
  555. state->min_vertex_index,
  556. state->vertex_count);
  557. count_to_render=0;
  558. start_index=i;
  559. node_id=tis[i].idx;
  560. }
  561. count_to_render++; //keep track of number of polygons of same kind
  562. }
  563. // Render any remaining polygons...
  564. if (count_to_render) {
  565. SortingNodeStruct* state=overlapping_nodes[node_id];
  566. Apply_Render_State(state->sorting_state);
  567. DX8Wrapper::Draw_Triangles(
  568. start_index*3,
  569. count_to_render,
  570. state->min_vertex_index,
  571. state->vertex_count);
  572. }
  573. // Release all references and return nodes back to the clean list for the frame...
  574. for (node_id=0;node_id<overlapping_node_count;++node_id) {
  575. SortingNodeStruct* state=overlapping_nodes[node_id];
  576. Release_Refs(state);
  577. clean_list.Add_Head(state);
  578. }
  579. overlapping_node_count=0;
  580. overlapping_polygon_count=0;
  581. overlapping_vertex_count=0;
  582. SNAPSHOT_SAY(("SortingSystem - Done flushing\n"));
  583. }
  584. // ----------------------------------------------------------------------------
  585. void SortingRendererClass::Flush()
  586. {
  587. Matrix4 old_view;
  588. Matrix4 old_world;
  589. DX8Wrapper::Get_Transform(D3DTS_VIEW,old_view);
  590. DX8Wrapper::Get_Transform(D3DTS_WORLD,old_world);
  591. while (SortingNodeStruct* state=sorted_list.Head()) {
  592. state->Remove();
  593. if ((state->sorting_state.index_buffer_type==BUFFER_TYPE_SORTING || state->sorting_state.index_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) &&
  594. (state->sorting_state.vertex_buffer_type==BUFFER_TYPE_SORTING || state->sorting_state.vertex_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING)) {
  595. Insert_To_Sorting_Pool(state);
  596. }
  597. else {
  598. DX8Wrapper::Set_Render_State(state->sorting_state);
  599. DX8Wrapper::Draw_Triangles(state->start_index,state->polygon_count,state->min_vertex_index,state->vertex_count);
  600. DX8Wrapper::Release_Render_State();
  601. Release_Refs(state);
  602. clean_list.Add_Head(state);
  603. }
  604. }
  605. Flush_Sorting_Pool();
  606. DX8Wrapper::Set_Index_Buffer(0,0);
  607. DX8Wrapper::Set_Vertex_Buffer(0);
  608. total_sorting_vertices=0;
  609. DynamicIBAccessClass::_Reset(false);
  610. DynamicVBAccessClass::_Reset(false);
  611. DX8Wrapper::Set_Transform(D3DTS_VIEW,old_view);
  612. DX8Wrapper::Set_Transform(D3DTS_WORLD,old_world);
  613. }
  614. // ----------------------------------------------------------------------------
  615. void SortingRendererClass::Deinit()
  616. {
  617. SortingNodeStruct *head = NULL;
  618. //
  619. // Flush the sorted list
  620. //
  621. while ((head = sorted_list.Head ()) != NULL) {
  622. sorted_list.Remove_Head ();
  623. delete head;
  624. }
  625. //
  626. // Flush the clean list
  627. //
  628. while ((head = clean_list.Head ()) != NULL) {
  629. clean_list.Remove_Head ();
  630. delete head;
  631. }
  632. delete[] vertex_z_array;
  633. vertex_z_array=NULL;
  634. vertex_z_array_count=0;
  635. delete[] polygon_z_array;
  636. polygon_z_array=NULL;
  637. polygon_z_array_count=0;
  638. delete[] node_id_array;
  639. node_id_array=NULL;
  640. node_id_array_count=0;
  641. delete[] sorted_node_id_array;
  642. sorted_node_id_array=NULL;
  643. sorted_node_id_array_count=0;
  644. delete[] polygon_index_array;
  645. polygon_index_array=NULL;
  646. polygon_index_array_count=0;
  647. delete[] temp_index_array;
  648. temp_index_array=NULL;
  649. temp_index_array_count=0;
  650. }
  651. // ----------------------------------------------------------------------------
  652. //
  653. // Insert a VolumeParticle triangle into the sorting system.
  654. //
  655. // ----------------------------------------------------------------------------
  656. void SortingRendererClass::Insert_VolumeParticle(
  657. const SphereClass& bounding_sphere,
  658. unsigned short start_index,
  659. unsigned short polygon_count,
  660. unsigned short min_vertex_index,
  661. unsigned short vertex_count,
  662. unsigned short layerCount)
  663. {
  664. if (!WW3D::Is_Sorting_Enabled()) {
  665. DX8Wrapper::Draw_Triangles(start_index,polygon_count,min_vertex_index,vertex_count);
  666. return;
  667. }
  668. //FOR VOLUME_PARTICLE LOGIC:
  669. // WE MUST MULTIPLY THE VERTCOUNT AND POLYCOUNT BY THE VOLUME_PARTICLE DEPTH
  670. DX8_RECORD_SORTING_RENDER( polygon_count * layerCount,vertex_count * layerCount);//THIS IS VOLUME_PARTICLE SPECIFIC
  671. SortingNodeStruct* state=Get_Sorting_Struct();
  672. DX8Wrapper::Get_Render_State(state->sorting_state);
  673. WWASSERT(((state->sorting_state.index_buffer_type==BUFFER_TYPE_SORTING || state->sorting_state.index_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) &&
  674. (state->sorting_state.vertex_buffer_type==BUFFER_TYPE_SORTING || state->sorting_state.vertex_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING)));
  675. state->bounding_sphere=bounding_sphere;
  676. state->start_index=start_index;
  677. state->min_vertex_index=min_vertex_index;
  678. state->polygon_count=polygon_count * layerCount;//THIS IS VOLUME_PARTICLE SPECIFIC
  679. state->vertex_count=vertex_count * layerCount;//THIS IS VOLUME_PARTICLE SPECIFIC
  680. SortingVertexBufferClass* vertex_buffer=static_cast<SortingVertexBufferClass*>(state->sorting_state.vertex_buffer);
  681. WWASSERT(vertex_buffer);
  682. WWASSERT(state->vertex_count<=vertex_buffer->Get_Vertex_Count());
  683. // Transform the center point to view space for sorting
  684. D3DXMATRIX mtx=(D3DXMATRIX&)state->sorting_state.world*(D3DXMATRIX&)state->sorting_state.view;
  685. D3DXVECTOR3 vec=(D3DXVECTOR3&)state->bounding_sphere.Center;
  686. D3DXVECTOR4 transformed_vec;
  687. D3DXVec3Transform(
  688. &transformed_vec,
  689. &vec,
  690. &mtx);
  691. state->transformed_center=Vector3(transformed_vec[0],transformed_vec[1],transformed_vec[2]);
  692. // BUT WHAT IS THE DEAL WITH THE VERTCOUNT AND POLYCOUNT BEING N BUT TRANSFORMED CENTER COUNT == 1
  693. //THE TRANSFORMED CENTER[2] IS THE ZBUFFER DEPTH
  694. /// @todo lorenzen sez use a bucket sort here... and stop copying so much data so many times
  695. SortingNodeStruct* node=sorted_list.Head();
  696. while (node) {
  697. if (state->transformed_center.Z>node->transformed_center.Z) {
  698. if (sorted_list.Head()==sorted_list.Tail())
  699. sorted_list.Add_Head(state);
  700. else
  701. state->Insert_Before(node);
  702. break;
  703. }
  704. node=node->Succ();
  705. }
  706. if (!node) sorted_list.Add_Tail(state);
  707. //#ifdef WWDEBUG
  708. // unsigned short* indices=NULL;
  709. // SortingIndexBufferClass* index_buffer=static_cast<SortingIndexBufferClass*>(state->sorting_state.index_buffer);
  710. // WWASSERT(index_buffer);
  711. // indices=index_buffer->index_buffer;
  712. // WWASSERT(indices);
  713. // indices+=state->start_index;
  714. // indices+=state->sorting_state.iba_offset;
  715. //
  716. // for (int i=0;i<state->polygon_count;++i) {
  717. // unsigned short idx1=indices[i*3]-state->min_vertex_index;
  718. // unsigned short idx2=indices[i*3+1]-state->min_vertex_index;
  719. // unsigned short idx3=indices[i*3+2]-state->min_vertex_index;
  720. // WWASSERT(idx1<state->vertex_count);
  721. // WWASSERT(idx2<state->vertex_count);
  722. // WWASSERT(idx3<state->vertex_count);
  723. // }
  724. //#endif
  725. }