dynamesh.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  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. *** 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 ***
  20. ***************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/dynamesh.cpp $*
  25. * *
  26. * $Author:: Greg_h $*
  27. * *
  28. * $Modtime:: 12/03/01 4:50p $*
  29. * *
  30. * $Revision:: 25 $*
  31. * *
  32. *-------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "dynamesh.h"
  36. #include "dx8vertexbuffer.h"
  37. #include "dx8indexbuffer.h"
  38. #include "dx8wrapper.h"
  39. #include "sortingrenderer.h"
  40. #include "rinfo.h"
  41. #include "camera.h"
  42. #include "dx8fvf.h"
  43. /*
  44. ** DynamicMeshModel implementation
  45. */
  46. DynamicMeshModel::DynamicMeshModel(unsigned int max_polys, unsigned int max_verts) :
  47. MeshGeometryClass(),
  48. DynamicMeshPNum(0),
  49. DynamicMeshVNum(0),
  50. MatDesc(NULL),
  51. MatInfo(NULL)
  52. {
  53. MatInfo = NEW_REF(MaterialInfoClass, ());
  54. MatDesc = W3DNEW MeshMatDescClass;
  55. MatDesc->Set_Polygon_Count(max_polys);
  56. MatDesc->Set_Vertex_Count(max_verts);
  57. Reset_Geometry(max_polys, max_verts);
  58. }
  59. DynamicMeshModel::DynamicMeshModel(unsigned int max_polys, unsigned int max_verts, MaterialInfoClass *mat_info) :
  60. MeshGeometryClass(),
  61. DynamicMeshPNum(0),
  62. DynamicMeshVNum(0),
  63. MatDesc(NULL),
  64. MatInfo(NULL)
  65. {
  66. MatInfo = mat_info;
  67. MatInfo->Add_Ref();
  68. MatDesc = W3DNEW MeshMatDescClass;
  69. MatDesc->Set_Polygon_Count(max_polys);
  70. MatDesc->Set_Vertex_Count(max_verts);
  71. Reset_Geometry(max_polys, max_verts);
  72. }
  73. DynamicMeshModel::DynamicMeshModel(const DynamicMeshModel &src) :
  74. MeshGeometryClass(src),
  75. DynamicMeshPNum(src.DynamicMeshPNum),
  76. DynamicMeshVNum(src.DynamicMeshVNum),
  77. MatDesc(NULL),
  78. MatInfo(NULL)
  79. {
  80. // Copy the material info structure.
  81. MatInfo = NEW_REF(MaterialInfoClass, (*(src.MatInfo)));
  82. // [SKB: Feb 21 2002 @ 11:47pm] :
  83. // Moved before the remapping cause I don't like referencing null.
  84. MatDesc = W3DNEW MeshMatDescClass;
  85. // remap!
  86. MaterialRemapperClass remapper(src.MatInfo, MatInfo);
  87. remapper.Remap_Mesh(src.MatDesc, MatDesc);
  88. }
  89. DynamicMeshModel::~DynamicMeshModel(void)
  90. {
  91. if (MatDesc) {
  92. delete MatDesc;
  93. MatDesc = NULL;
  94. }
  95. REF_PTR_RELEASE(MatInfo);
  96. }
  97. void DynamicMeshModel::Compute_Plane_Equations(void)
  98. {
  99. // Make sure the arrays are allocated before we do this
  100. get_vert_normals();
  101. Vector4 * planes = get_planes(true);
  102. // Set the poly and vertex counts to the dynamic counts, call the base class function, then
  103. // set them back.
  104. int old_poly_count = PolyCount;
  105. int old_vert_count = VertexCount;
  106. PolyCount = DynamicMeshPNum;
  107. VertexCount = DynamicMeshVNum;
  108. MeshGeometryClass::Compute_Plane_Equations(planes);
  109. PolyCount = old_poly_count;
  110. VertexCount = old_vert_count;
  111. }
  112. void DynamicMeshModel::Compute_Vertex_Normals(void)
  113. {
  114. // Make sure the arrays are allocated before we do this
  115. Vector3 * vnorms = get_vert_normals();
  116. get_planes(true);
  117. // Set the poly and vertex counts to the dynamic counts, call the base class function, then
  118. // set them back.
  119. int old_poly_count = PolyCount;
  120. int old_vert_count = VertexCount;
  121. PolyCount = DynamicMeshPNum;
  122. VertexCount = DynamicMeshVNum;
  123. MeshGeometryClass::Compute_Vertex_Normals(vnorms);
  124. PolyCount = old_poly_count;
  125. VertexCount = old_vert_count;
  126. }
  127. void DynamicMeshModel::Compute_Bounds(Vector3 * verts)
  128. {
  129. // Set the poly and vertex counts to the dynamic counts, call the base class function, then
  130. // set them back.
  131. int old_poly_count = PolyCount;
  132. int old_vert_count = VertexCount;
  133. PolyCount = DynamicMeshPNum;
  134. VertexCount = DynamicMeshVNum;
  135. MeshGeometryClass::Compute_Bounds(verts);
  136. PolyCount = old_poly_count;
  137. VertexCount = old_vert_count;
  138. }
  139. void DynamicMeshModel::Reset(void)
  140. {
  141. Set_Counts(0, 0);
  142. int polycount = Get_Polygon_Count();
  143. int vertcount = Get_Vertex_Count();
  144. Reset_Geometry(polycount, vertcount);
  145. MatDesc->Reset(polycount, vertcount, 1);
  146. REF_PTR_RELEASE(MatInfo);
  147. MatInfo = NEW_REF(MaterialInfoClass, ());
  148. }
  149. void DynamicMeshModel::Render(RenderInfoClass & rinfo)
  150. {
  151. // Process texture reductions:
  152. // MatInfo->Process_Texture_Reduction();
  153. unsigned buffer_type=(Get_Flag(MeshGeometryClass::SORT)&& WW3D::Is_Sorting_Enabled()) ? BUFFER_TYPE_DYNAMIC_SORTING : BUFFER_TYPE_DYNAMIC_DX8;
  154. /*
  155. ** Write the vertex data to the vertex buffer. We assume the FVF contains positions, normals,
  156. ** one texture channel, and the diffuse color channel (color0). If it does not contain all
  157. ** these components, the code will fail.
  158. */
  159. DynamicVBAccessClass dynamic_vb(buffer_type,dynamic_fvf_type,DynamicMeshVNum);
  160. const FVFInfoClass &fvf_info = dynamic_vb.FVF_Info();
  161. { // scope for lock
  162. DynamicVBAccessClass::WriteLockClass lock(&dynamic_vb);
  163. unsigned char *vertices = (unsigned char*)lock.Get_Formatted_Vertex_Array();
  164. const Vector3 *locs = Get_Vertex_Array();
  165. const Vector3 *normals = Get_Vertex_Normal_Array();
  166. const Vector2 *uvs = MatDesc->Get_UV_Array_By_Index(0, false);
  167. const Vector2 *uv1s = MatDesc->Get_UV_Array_By_Index(1, false);
  168. const unsigned *colors = MatDesc->Get_Color_Array(0, false);
  169. const static Vector3 default_normal(0.0f, 0.0f, 0.0f);
  170. const static Vector2 default_uv(0.0f, 0.0f);
  171. const unsigned int default_color = 0xFFFFFFFF;
  172. for (int i=0; i < DynamicMeshVNum; i++)
  173. {
  174. *(Vector3 *)(vertices + fvf_info.Get_Location_Offset()) = locs[i];
  175. *(Vector3 *)(vertices + fvf_info.Get_Normal_Offset()) = normals[i];
  176. if (uvs) {
  177. *(Vector2 *)(vertices + fvf_info.Get_Tex_Offset(0)) = uvs[i];
  178. } else {
  179. *(Vector2 *)(vertices + fvf_info.Get_Tex_Offset(0)) = default_uv;
  180. }
  181. if (uv1s) {
  182. *(Vector2 *)(vertices + fvf_info.Get_Tex_Offset(1)) = uv1s[i];
  183. } else {
  184. *(Vector2 *)(vertices + fvf_info.Get_Tex_Offset(1)) = default_uv;
  185. }
  186. if (colors) {
  187. *(unsigned int *)(vertices + fvf_info.Get_Diffuse_Offset()) = colors[i];
  188. } else {
  189. *(unsigned int *)(vertices + fvf_info.Get_Diffuse_Offset()) = default_color;
  190. }
  191. vertices += fvf_info.Get_FVF_Size();
  192. }
  193. } // end scope for lock
  194. /*
  195. ** Write index data to index buffers
  196. */
  197. DynamicIBAccessClass dynamic_ib(buffer_type,DynamicMeshPNum * 3);
  198. const TriIndex *tris = Get_Polygon_Array();
  199. { // scope for lock
  200. DynamicIBAccessClass::WriteLockClass lock(&dynamic_ib);
  201. unsigned short * indices = lock.Get_Index_Array();
  202. for (int i=0; i < DynamicMeshPNum; i++)
  203. {
  204. indices[i*3 + 0] = (unsigned short)tris[i][0];
  205. indices[i*3 + 1] = (unsigned short)tris[i][1];
  206. indices[i*3 + 2] = (unsigned short)tris[i][2];
  207. }
  208. } // end scope for lock
  209. /*
  210. ** Set vertex and index buffers
  211. */
  212. DX8Wrapper::Set_Vertex_Buffer(dynamic_vb);
  213. DX8Wrapper::Set_Index_Buffer(dynamic_ib,0);
  214. /*
  215. ** Draw dynamesh, one pass at a time
  216. */
  217. unsigned int pass_count = Get_Pass_Count();
  218. for (unsigned int pass = 0; pass < pass_count; pass++) {
  219. /*
  220. ** Set current render states (texture, vertex material, shader). Scan triangles until one
  221. ** of these changes, and then draw.
  222. */
  223. // The vertex index range used
  224. unsigned short min_vert_idx = DynamicMeshVNum - 1;
  225. unsigned short max_vert_idx = 0;
  226. unsigned short start_tri_idx = 0;
  227. unsigned short cur_tri_idx = 0;
  228. bool done = false;
  229. bool texture_changed = false;
  230. bool texture1_changed = false;
  231. bool material_changed = false;
  232. bool shader_changed = false;
  233. TextureClass **texture_array0 = NULL;
  234. TexBufferClass * tex_buf = MatDesc->Get_Texture_Array(pass, 0, false);
  235. if (tex_buf) {
  236. texture_array0 = tex_buf->Get_Array();
  237. } else {
  238. texture_array0 = NULL;
  239. }
  240. TextureClass **texture_array1 = NULL;
  241. TexBufferClass * tex_buf1 = MatDesc->Get_Texture_Array(pass, 1, false);
  242. if (tex_buf1) {
  243. texture_array1 = tex_buf1->Get_Array();
  244. } else {
  245. texture_array1 = NULL;
  246. }
  247. VertexMaterialClass **material_array = NULL;
  248. MatBufferClass * mat_buf = MatDesc->Get_Material_Array(pass, false);
  249. if (mat_buf) {
  250. material_array = mat_buf->Get_Array();
  251. } else {
  252. material_array = NULL;
  253. }
  254. ShaderClass *shader_array = MatDesc->Get_Shader_Array(pass, false);
  255. // Set the DX8 state to the first triangle's state
  256. if (texture_array0) {
  257. DX8Wrapper::Set_Texture(0,texture_array0[0]);
  258. } else {
  259. DX8Wrapper::Set_Texture(0,MatDesc->Peek_Single_Texture(pass, 0));
  260. }
  261. if (texture_array1) {
  262. DX8Wrapper::Set_Texture(1,texture_array1[0]);
  263. } else {
  264. DX8Wrapper::Set_Texture(1,MatDesc->Peek_Single_Texture(pass, 1));
  265. }
  266. if (material_array) {
  267. DX8Wrapper::Set_Material(material_array[tris[0].I]);
  268. } else {
  269. DX8Wrapper::Set_Material(MatDesc->Peek_Single_Material(pass));
  270. }
  271. if (shader_array) {
  272. DX8Wrapper::Set_Shader(shader_array[0]);
  273. } else {
  274. DX8Wrapper::Set_Shader(MatDesc->Get_Single_Shader(pass));
  275. }
  276. SphereClass sphere(Vector3(0.0f,0.0f,0.0f),0.0f);
  277. Get_Bounding_Sphere(&sphere);
  278. // If no texture, shader or material arrays for this pass just draw and go to next pass
  279. if (!texture_array0 && !texture_array1 && !material_array && !shader_array) {
  280. if (buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) {
  281. SortingRendererClass::Insert_Triangles(sphere,0, DynamicMeshPNum, 0, DynamicMeshVNum);
  282. }
  283. else {
  284. DX8Wrapper::Draw_Triangles(0, DynamicMeshPNum, 0, DynamicMeshVNum);
  285. }
  286. continue;
  287. }
  288. while (!done) {
  289. // Add vertex indices of tri[cur_tri_idx] to min_vert_idx, max_vert_idx
  290. const TriIndex &tri = tris[cur_tri_idx];
  291. unsigned short min_idx = (unsigned short)MIN(MIN(tri.I, tri.J), tri.K);
  292. unsigned short max_idx = (unsigned short)MAX(MAX(tri.I, tri.J), tri.K);
  293. min_vert_idx = MIN(min_vert_idx, min_idx);
  294. max_vert_idx = MAX(max_vert_idx, max_idx);
  295. // Check the next triangle to see if the current run has ended.
  296. unsigned short next_tri_idx = cur_tri_idx + 1;
  297. done = next_tri_idx >= DynamicMeshPNum;
  298. if (done) {
  299. texture_changed = false;
  300. texture1_changed = false;
  301. material_changed = false;
  302. shader_changed = false;
  303. } else {
  304. texture_changed = texture_array0 && texture_array0[cur_tri_idx] != texture_array0[next_tri_idx];
  305. texture1_changed = texture_array1 && texture_array1[cur_tri_idx] != texture_array1[next_tri_idx];
  306. material_changed = material_array && material_array[tris[cur_tri_idx].I] != material_array[tris[next_tri_idx].I];
  307. shader_changed = shader_array && shader_array[cur_tri_idx] != shader_array[next_tri_idx];
  308. }
  309. // If run ends (mesh ends or state changes) draw, reset indices, set state for next run.
  310. if (done || texture_changed || material_changed || shader_changed) {
  311. if (buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) {
  312. SortingRendererClass::Insert_Triangles(
  313. sphere,
  314. (start_tri_idx * 3),
  315. (1 + cur_tri_idx - start_tri_idx),
  316. min_vert_idx,
  317. 1 + max_vert_idx - min_vert_idx);
  318. }
  319. else {
  320. DX8Wrapper::Draw_Triangles(
  321. (start_tri_idx * 3),
  322. (1 + cur_tri_idx - start_tri_idx),
  323. min_vert_idx,
  324. 1 + max_vert_idx - min_vert_idx);
  325. }
  326. start_tri_idx = next_tri_idx;
  327. min_vert_idx = DynamicMeshVNum - 1;
  328. max_vert_idx = 0;
  329. if (texture_changed) DX8Wrapper::Set_Texture(0,texture_array0[next_tri_idx]);
  330. if (texture1_changed) DX8Wrapper::Set_Texture(1,texture_array1[next_tri_idx]);
  331. if (material_changed) DX8Wrapper::Set_Material(material_array[tris[next_tri_idx].I]);
  332. if (shader_changed) DX8Wrapper::Set_Shader(shader_array[next_tri_idx]);
  333. }
  334. cur_tri_idx = next_tri_idx;
  335. } // while (!done)
  336. } // for (pass)
  337. }
  338. void DynamicMeshModel::Initialize_Texture_Array(int pass, int stage, TextureClass *texture)
  339. {
  340. TexBufferClass * texlist = MatDesc->Get_Texture_Array(pass, 0, true);
  341. for (int lp = 0; lp < PolyCount; lp++) {
  342. texlist->Set_Element(lp, texture);
  343. }
  344. }
  345. void DynamicMeshModel::Initialize_Material_Array(int pass, VertexMaterialClass *vmat)
  346. {
  347. MatBufferClass * vertmatlist = MatDesc->Get_Material_Array(pass, true);
  348. for (int lp = 0; lp < VertexCount; lp++) {
  349. vertmatlist->Set_Element(lp, vmat);
  350. }
  351. }
  352. void DynamicMeshClass::Render(RenderInfoClass & rinfo)
  353. {
  354. if (Is_Not_Hidden_At_All() == false) return;
  355. // test for an empty mesh..
  356. if (PolyCount == 0 ) return;
  357. // If static sort lists are enabled and this mesh has a sort level, put it on the list instead
  358. // of rendering it.
  359. if (WW3D::Are_Static_Sort_Lists_Enabled() && SortLevel != SORT_LEVEL_NONE) {
  360. WW3D::Add_To_Static_Sort_List(this, SortLevel);
  361. } else {
  362. const FrustumClass & frustum = rinfo.Camera.Get_Frustum();
  363. if (CollisionMath::Overlap_Test(frustum, Get_Bounding_Box()) != CollisionMath::OUTSIDE) {
  364. DX8Wrapper::Set_Transform(D3DTS_WORLD, Transform);
  365. Model->Render(rinfo);
  366. }
  367. }
  368. }
  369. bool DynamicMeshClass::End_Vertex()
  370. {
  371. // check that we have room for a new vertex
  372. WWASSERT(VertCount < Model->Get_Vertex_Count());
  373. // if we are a multi-material object record the material
  374. int pass = Get_Pass_Count();
  375. while (pass--) {
  376. if (MultiVertexMaterial[pass]) {
  377. VertexMaterialClass *mat = Peek_Material_Info()->Get_Vertex_Material(VertexMaterialIdx[pass]);
  378. Model->Set_Material(VertCount, mat, pass);
  379. REF_PTR_RELEASE(mat);
  380. }
  381. }
  382. // if we are multi colored, record the color
  383. for (int color_array_index = 0; color_array_index < MAX_COLOR_ARRAYS; color_array_index++) {
  384. if (MultiVertexColor[color_array_index]) {
  385. // Vector4 * color = &((Model->Get_Color_Array(color_array_index))[VertCount]);
  386. // color->X = CurVertexColor[color_array_index].X;
  387. // color->Y = CurVertexColor[color_array_index].Y;
  388. // color->Z = CurVertexColor[color_array_index].Z;
  389. // color->W = CurVertexColor[color_array_index].W;
  390. unsigned * color = &((Model->Get_Color_Array(color_array_index))[VertCount]);
  391. *color=DX8Wrapper::Convert_Color_Clamp(CurVertexColor[color_array_index]);
  392. }
  393. }
  394. // mark this vertex as being complete
  395. VertCount++;
  396. TriVertexCount++;
  397. // if we have 3 or more vertices, add a new poly
  398. if (TriVertexCount >= 3) {
  399. // check that we have room for a new poly
  400. WWASSERT(PolyCount < Model->Get_Polygon_Count());
  401. // set vertex indices
  402. TriIndex *poly = &(Model->Get_Non_Const_Polygon_Array())[PolyCount];
  403. if (TriMode == TRI_MODE_STRIPS) {
  404. (*poly)[0] = VertCount-3;
  405. (*poly)[1] = VertCount-2;
  406. (*poly)[2] = VertCount-1;
  407. // for every other tri, reverse vertex order
  408. if (Flip_Face()) {
  409. (*poly)[1] = VertCount-1;
  410. (*poly)[2] = VertCount-2;
  411. }
  412. } else {
  413. (*poly)[0] = FanVertex;
  414. (*poly)[1] = VertCount-2;
  415. (*poly)[2] = VertCount-1;
  416. }
  417. // check each pass
  418. int pass = Get_Pass_Count();
  419. while (pass--) {
  420. // If we are multi texture
  421. if (MultiTexture[pass]) {
  422. TextureClass *tex = Peek_Material_Info()->Get_Texture(TextureIdx[pass]);
  423. Model->Set_Texture(PolyCount, tex, pass);
  424. REF_PTR_RELEASE(tex);
  425. }
  426. }
  427. // increase the count and record that we have a new material
  428. PolyCount++;
  429. Model->Set_Counts(PolyCount, VertCount);
  430. }
  431. return true;
  432. }
  433. /******************************************************************
  434. **
  435. ** DynamicMeshClass
  436. **
  437. *******************************************************************/
  438. DynamicMeshClass::DynamicMeshClass(int max_poly, int max_vert) :
  439. Model(NULL),
  440. PolyCount(0),
  441. VertCount(0),
  442. TriVertexCount(0),
  443. FanVertex(0),
  444. TriMode(TRI_MODE_STRIPS),
  445. SortLevel(SORT_LEVEL_NONE)
  446. {
  447. int pass = MAX_PASSES;
  448. while (pass--) {
  449. MultiTexture[pass] = false;
  450. TextureIdx[pass] = -1;
  451. MultiVertexMaterial[pass] = false;
  452. VertexMaterialIdx[pass] = -1;
  453. }
  454. for (int color_array_index = 0; color_array_index < MAX_COLOR_ARRAYS; color_array_index++) {
  455. MultiVertexColor[color_array_index] = false;
  456. CurVertexColor[color_array_index].Set(1.0f, 1.0f, 1.0f, 1.0f);
  457. }
  458. Model = NEW_REF(DynamicMeshModel, (max_poly, max_vert));
  459. }
  460. DynamicMeshClass::DynamicMeshClass(int max_poly, int max_vert, MaterialInfoClass *mat_info) :
  461. Model(NULL),
  462. PolyCount(0),
  463. VertCount(0),
  464. TriVertexCount(0),
  465. FanVertex(0),
  466. TriMode(TRI_MODE_STRIPS),
  467. SortLevel(SORT_LEVEL_NONE)
  468. {
  469. int pass = MAX_PASSES;
  470. while (pass--) {
  471. MultiTexture[pass] = false;
  472. TextureIdx[pass] = -1;
  473. MultiVertexMaterial[pass] = false;
  474. VertexMaterialIdx[pass] = -1;
  475. }
  476. for (int color_array_index = 0; color_array_index < MAX_COLOR_ARRAYS; color_array_index++) {
  477. MultiVertexColor[color_array_index] = false;
  478. CurVertexColor[color_array_index].Set(1.0f, 1.0f, 1.0f, 1.0f);
  479. }
  480. Model = NEW_REF(DynamicMeshModel, (max_poly, max_vert, mat_info));
  481. }
  482. DynamicMeshClass::DynamicMeshClass(const DynamicMeshClass & src) :
  483. RenderObjClass(src),
  484. Model(NULL),
  485. PolyCount(src.PolyCount),
  486. VertCount(src.VertCount),
  487. TriVertexCount(src.TriVertexCount),
  488. FanVertex(src.FanVertex),
  489. TriMode(src.TriMode),
  490. SortLevel(src.SortLevel)
  491. {
  492. int pass = MAX_PASSES;
  493. while (pass--) {
  494. MultiTexture[pass] = src.MultiTexture[pass];
  495. TextureIdx[pass] = src.TextureIdx[pass];
  496. MultiVertexMaterial[pass] = src.MultiVertexMaterial[pass];
  497. VertexMaterialIdx[pass] = src.VertexMaterialIdx[pass];
  498. MultiVertexColor[pass] = src.MultiVertexColor[pass];
  499. CurVertexColor[pass] = src.CurVertexColor[pass];
  500. }
  501. for (int color_array_index = 0; color_array_index < MAX_COLOR_ARRAYS; color_array_index++) {
  502. MultiVertexColor[color_array_index] = src.MultiVertexColor[color_array_index];
  503. CurVertexColor[color_array_index] = src.CurVertexColor[color_array_index];
  504. }
  505. Model = NEW_REF(DynamicMeshModel, (*(src.Model)));
  506. }
  507. void DynamicMeshClass::Resize(int max_polys, int max_verts)
  508. {
  509. Reset();
  510. REF_PTR_RELEASE(Model);
  511. Model = NEW_REF(DynamicMeshModel, (max_polys, max_verts));
  512. // reset all the texture & vertex material indices
  513. int pass = MAX_PASSES;
  514. while (pass--) {
  515. TextureIdx[pass] = -1;
  516. VertexMaterialIdx[pass] = -1;
  517. MultiVertexMaterial[pass] = false;
  518. }
  519. }
  520. DynamicMeshClass::~DynamicMeshClass()
  521. {
  522. REF_PTR_RELEASE(Model);
  523. }
  524. RenderObjClass * DynamicMeshClass::Clone(void) const
  525. {
  526. return NEW_REF(DynamicMeshClass, (*this));
  527. }
  528. void DynamicMeshClass::Location(float x, float y, float z)
  529. {
  530. Vector3 * loc = Model->Get_Vertex_Array();
  531. assert(loc);
  532. loc[VertCount].X = x;
  533. loc[VertCount].Y = y;
  534. loc[VertCount].Z = z;
  535. }
  536. /*
  537. ** For moving a vertex after the DynaMesh has already been created.
  538. */
  539. void DynamicMeshClass::Move_Vertex(int index, float x, float y, float z)
  540. {
  541. Vector3 * loc = Model->Get_Vertex_Array();
  542. assert(loc);
  543. loc[index][0] = x;
  544. loc[index][1] = y;
  545. loc[index][2] = z;
  546. }
  547. /*
  548. ** Get a vertex value.
  549. */
  550. void DynamicMeshClass::Get_Vertex(int index, float &x, float &y, float &z)
  551. {
  552. Vector3 * loc = Model->Get_Vertex_Array();
  553. assert(loc);
  554. x = loc[index][0];
  555. y = loc[index][1];
  556. z = loc[index][2];
  557. }
  558. /*
  559. ** Offset the entire mesh
  560. */
  561. void DynamicMeshClass::Translate_Vertices(const Vector3 & offset)
  562. {
  563. Vector3 * loc = Model->Get_Vertex_Array();
  564. assert(loc);
  565. for (int i=0; i < Get_Num_Vertices(); i++) {
  566. loc[i].X += offset.X;
  567. loc[i].Y += offset.Y;
  568. loc[i].Z += offset.Z;
  569. }
  570. Set_Dirty_Bounds();
  571. Set_Dirty_Planes();
  572. }
  573. int DynamicMeshClass::Set_Vertex_Material(int idx, int pass)
  574. {
  575. assert(idx < Peek_Material_Info()->Vertex_Material_Count());
  576. VertexMaterialIdx[pass] = idx;
  577. if (!MultiVertexMaterial[pass]) {
  578. // WWASSERT( VertexMaterialIdx[pass] == 0);
  579. VertexMaterialClass *mat = Peek_Material_Info()->Get_Vertex_Material(VertexMaterialIdx[pass]);
  580. Model->Set_Single_Material(mat, pass);
  581. mat->Release_Ref();
  582. }
  583. return VertexMaterialIdx[pass];
  584. }
  585. int DynamicMeshClass::Set_Vertex_Material(VertexMaterialClass *material, bool dont_search, int pass)
  586. {
  587. // Check if same as the last vertex material
  588. if (Peek_Material_Info()->Vertex_Material_Count() && (VertexMaterialIdx[pass] != -1) && Peek_Material_Info()->Peek_Vertex_Material(VertexMaterialIdx[pass]) == material) {
  589. return VertexMaterialIdx[pass];
  590. }
  591. // if there are vertex materials in the list then we may have just jumped
  592. // to becoming a multi-vertex-material object. Take care of that here.
  593. if ((!MultiVertexMaterial[pass]) && Peek_Material_Info()->Vertex_Material_Count() && (VertexMaterialIdx[pass] != -1) && Peek_Material_Info()->Peek_Vertex_Material(VertexMaterialIdx[pass]) != material) {
  594. // allocate the array of per-vertex vertex material overrides
  595. VertexMaterialClass *mat = Peek_Material_Info()->Get_Vertex_Material(VertexMaterialIdx[pass]);
  596. Model->Initialize_Material_Array(pass, mat);
  597. mat->Release_Ref();
  598. // flag that we need to write the per -vertex vertex material override array
  599. MultiVertexMaterial[pass] = true;
  600. }
  601. // add the material to the material info class if we cant find it in the
  602. // list. if we are not supposed to search the list for it then just add
  603. // it.
  604. if (!dont_search) {
  605. for (int lp = 0, found = 0; lp < Peek_Material_Info()->Vertex_Material_Count(); lp ++) {
  606. VertexMaterialClass *mat = Peek_Material_Info()->Get_Vertex_Material(lp);
  607. if (material == mat) {
  608. VertexMaterialIdx[pass] = lp;
  609. found = true;
  610. mat->Release_Ref();
  611. break;
  612. }
  613. mat->Release_Ref();
  614. }
  615. if (!found) {
  616. Peek_Material_Info()->Add_Vertex_Material(material);
  617. VertexMaterialIdx[pass] = Peek_Material_Info()->Vertex_Material_Count() - 1;
  618. }
  619. } else {
  620. Peek_Material_Info()->Add_Vertex_Material(material);
  621. VertexMaterialIdx[pass] = Peek_Material_Info()->Vertex_Material_Count() - 1;
  622. }
  623. if (!MultiVertexMaterial[pass]) {
  624. Model->Set_Single_Material(Peek_Material_Info()->Peek_Vertex_Material(VertexMaterialIdx[pass]), pass);
  625. }
  626. return(VertexMaterialIdx[pass]);
  627. }
  628. int DynamicMeshClass::Set_Texture(int idx, int pass)
  629. {
  630. WWASSERT(idx < Peek_Material_Info()->Texture_Count());
  631. TextureIdx[pass] = idx;
  632. if (!MultiTexture[pass]) {
  633. TextureClass *tex = Peek_Material_Info()->Get_Texture(TextureIdx[pass]);
  634. Model->Set_Single_Texture(tex, pass);
  635. tex->Release_Ref();
  636. }
  637. return TextureIdx[pass];
  638. }
  639. int DynamicMeshClass::Set_Texture(TextureClass *texture, bool dont_search, int pass)
  640. {
  641. // Check if same as the last texture
  642. if (Peek_Material_Info()->Texture_Count() && (TextureIdx[pass] != -1) && Peek_Material_Info()->Peek_Texture(TextureIdx[pass]) == texture) {
  643. return TextureIdx[pass];
  644. }
  645. // if there are textures in the list then we may have just jumped
  646. // to becoming a multi-texture object. Take care of that here.
  647. if ((!MultiTexture[pass]) && Peek_Material_Info()->Texture_Count() && (TextureIdx[pass] != -1) && Peek_Material_Info()->Peek_Texture(TextureIdx[pass]) != texture) {
  648. // allocate the array of per polygon material over-rides
  649. TextureClass *tex = Peek_Material_Info()->Get_Texture(TextureIdx[pass]);
  650. Model->Initialize_Texture_Array(pass, 0, tex);
  651. tex->Release_Ref();
  652. // flag that we need to write the per polygon material overide array
  653. MultiTexture[pass] = true;
  654. }
  655. // add the material to the material info class if we cant find it in the
  656. // list. if we are not supposed to search the list for it then just add
  657. // it.
  658. if (!dont_search) {
  659. for (int lp = 0, found = 0; lp < Peek_Material_Info()->Texture_Count(); lp ++) {
  660. TextureClass *tex = Peek_Material_Info()->Get_Texture(lp);
  661. if (texture == tex) {
  662. TextureIdx[pass] = lp;
  663. found = true;
  664. tex->Release_Ref();
  665. break;
  666. }
  667. tex->Release_Ref();
  668. }
  669. if (!found) {
  670. Peek_Material_Info()->Add_Texture(texture);
  671. TextureIdx[pass] = Peek_Material_Info()->Texture_Count() - 1;
  672. }
  673. } else {
  674. Peek_Material_Info()->Add_Texture(texture);
  675. TextureIdx[pass] = Peek_Material_Info()->Texture_Count() - 1;
  676. }
  677. if (!MultiTexture[pass]) {
  678. TextureClass *tex = Peek_Material_Info()->Get_Texture(TextureIdx[pass]);
  679. Model->Set_Single_Texture(tex, pass);
  680. tex->Release_Ref();
  681. }
  682. return(TextureIdx[pass]);
  683. }
  684. /*
  685. **
  686. */
  687. // Remap locations to match a screen
  688. void DynamicScreenMeshClass::Location( float x, float y, float z)
  689. {
  690. DynamicMeshClass::Location( (x * 2) - 1, Aspect - (y * 2 * Aspect), 0);
  691. }
  692. // For moving a vertex after the DynaMesh has already been created.
  693. void DynamicScreenMeshClass::Move_Vertex(int index, float x, float y, float z)
  694. {
  695. DynamicMeshClass::Move_Vertex( index, (x * 2) - 1, Aspect - (y * 2 * Aspect), 0);
  696. }
  697. // Set position
  698. void DynamicScreenMeshClass::Set_Position(const Vector3 &v)
  699. {
  700. DynamicMeshClass::Set_Position(Vector3(v.X * 2, -(v.Y * 2 * Aspect), 0));
  701. }
  702. void DynamicScreenMeshClass::Reset( void )
  703. {
  704. Reset_Flags();
  705. Reset_Mesh_Counters();
  706. }