dynamesh.cpp 24 KB

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