dynamesh.cpp 25 KB

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