meshmdl.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  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 : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/meshmdl.cpp $*
  25. * *
  26. * Org Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 4:04p $*
  31. * *
  32. * $Revision:: 48 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. *---------------------------------------------------------------------------------------------*
  36. * Functions: *
  37. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  38. #include "meshmdl.h"
  39. #include "matinfo.h"
  40. #include "aabtree.h"
  41. #include "htree.h"
  42. #include "vp.h"
  43. #include "visrasterizer.h"
  44. #include "dx8polygonrenderer.h"
  45. #include "bwrender.h"
  46. #include "camera.h"
  47. #include "dx8renderer.h"
  48. #include "hashtemplate.h"
  49. /*
  50. ** Temporary Buffers
  51. ** These buffers are used by the skin code for temporary storage of the deformed vertices and
  52. ** vertex normals.
  53. */
  54. static DynamicVectorClass<Vector3> _TempVertexBuffer;
  55. static DynamicVectorClass<Vector3> _TempNormalBuffer;
  56. static DynamicVectorClass<Vector4> _TempTransformedVertexBuffer;
  57. static DynamicVectorClass<unsigned long> _TempClipFlagBuffer;
  58. /*
  59. **
  60. ** MeshModelClass Implementation
  61. **
  62. */
  63. MeshModelClass::MeshModelClass(void) :
  64. DefMatDesc(NULL),
  65. AlternateMatDesc(NULL),
  66. CurMatDesc(NULL),
  67. MatInfo(NULL),
  68. GapFiller(NULL)
  69. {
  70. Set_Flag(DIRTY_BOUNDS,true);
  71. DefMatDesc = W3DNEW MeshMatDescClass;
  72. CurMatDesc = DefMatDesc;
  73. MatInfo = NEW_REF( MaterialInfoClass, () );
  74. return ;
  75. }
  76. MeshModelClass::MeshModelClass(const MeshModelClass & that) :
  77. MeshGeometryClass(that),
  78. DefMatDesc(NULL),
  79. AlternateMatDesc(NULL),
  80. CurMatDesc(NULL),
  81. MatInfo(NULL),
  82. GapFiller(NULL),
  83. HasBeenInUse(false)
  84. {
  85. DefMatDesc = W3DNEW MeshMatDescClass(*(that.DefMatDesc));
  86. if (that.AlternateMatDesc != NULL) {
  87. AlternateMatDesc = W3DNEW MeshMatDescClass(*(that.AlternateMatDesc));
  88. }
  89. CurMatDesc = DefMatDesc;
  90. clone_materials(that);
  91. return ;
  92. }
  93. MeshModelClass::~MeshModelClass(void)
  94. {
  95. // WWDEBUG_SAY(("Note: Mesh %s was never used\n",Get_Name()));
  96. TheDX8MeshRenderer.Unregister_Mesh_Type(this);
  97. Reset(0,0,0);
  98. REF_PTR_RELEASE(MatInfo);
  99. if (DefMatDesc != NULL) {
  100. delete DefMatDesc;
  101. }
  102. if (AlternateMatDesc != NULL) {
  103. delete AlternateMatDesc;
  104. }
  105. return ;
  106. }
  107. MeshModelClass & MeshModelClass::operator = (const MeshModelClass & that)
  108. {
  109. if (this != &that) {
  110. // Remove all polygon renderers, this will remove the mesh from the rendering system.
  111. // The mesh will be initialized to rendering system the next time it is rendered.
  112. TheDX8MeshRenderer.Unregister_Mesh_Type(this);
  113. MeshGeometryClass::operator = (that);
  114. *DefMatDesc = *(that.DefMatDesc);
  115. CurMatDesc = DefMatDesc;
  116. if (AlternateMatDesc != NULL) {
  117. delete AlternateMatDesc;
  118. AlternateMatDesc = NULL;
  119. }
  120. if (that.AlternateMatDesc != NULL) {
  121. AlternateMatDesc = W3DNEW MeshMatDescClass(*(that.AlternateMatDesc));
  122. }
  123. clone_materials(that);
  124. if (GapFiller) {
  125. // DMS - using approriate deallocation method
  126. delete GapFiller;
  127. GapFiller=NULL;
  128. }
  129. if (that.GapFiller) GapFiller=W3DNEW GapFillerClass(*that.GapFiller);
  130. }
  131. return * this;
  132. }
  133. void MeshModelClass::Reset(int polycount,int vertcount,int passcount)
  134. {
  135. //DMS - We must delete the gapfiller object BEFORE the geometry is reset. Otherwise,
  136. // the number of stages and passes gets reset and the gapfiller cannot deallocate properly.
  137. delete GapFiller;
  138. GapFiller=NULL;
  139. Reset_Geometry(polycount,vertcount);
  140. // Release everything we have and reset to initial state
  141. TheDX8MeshRenderer.Unregister_Mesh_Type(this);
  142. MatInfo->Reset();
  143. DefMatDesc->Reset(polycount,vertcount,passcount);
  144. if (AlternateMatDesc != NULL) {
  145. delete AlternateMatDesc;
  146. AlternateMatDesc = NULL;
  147. }
  148. CurMatDesc = DefMatDesc;
  149. return ;
  150. }
  151. void MeshModelClass::Register_For_Rendering()
  152. {
  153. HasBeenInUse=true;
  154. //WW3D::Set_NPatches_Level(1);
  155. if (WW3D::Get_NPatches_Level()>1) {
  156. if (WW3D::Get_NPatches_Gap_Filling_Mode()!=WW3D::NPATCHES_GAP_FILLING_DISABLED) {
  157. Init_For_NPatch_Rendering();
  158. }
  159. else if (GapFiller) {
  160. delete GapFiller;
  161. GapFiller=NULL;
  162. }
  163. }
  164. else {
  165. if (WW3D::Get_NPatches_Gap_Filling_Mode()==WW3D::NPATCHES_GAP_FILLING_FORCE) {
  166. Init_For_NPatch_Rendering();
  167. }
  168. else if (GapFiller) {
  169. delete GapFiller;
  170. GapFiller=NULL;
  171. }
  172. }
  173. TheDX8MeshRenderer.Register_Mesh_Type(this);
  174. }
  175. void MeshModelClass::Replace_Texture(TextureClass* texture,TextureClass* new_texture)
  176. {
  177. WWASSERT(texture);
  178. WWASSERT(new_texture);
  179. for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
  180. for (int pass=0;pass<Get_Pass_Count();++pass) {
  181. if (Has_Texture_Array(pass,stage)) {
  182. for (int i=0;i<Get_Polygon_Count();++i) {
  183. if (Peek_Texture(i,pass,stage)==texture) {
  184. Set_Texture(i,new_texture,pass,stage);
  185. }
  186. }
  187. }
  188. else {
  189. if (Peek_Single_Texture(pass,stage)==texture) {
  190. Set_Single_Texture(new_texture,pass,stage);
  191. }
  192. }
  193. // If this mesh model has been initialized for rendering we need to tell the rendering
  194. // system to change texturing as well.
  195. DX8FVFCategoryContainer* fvf_category=Peek_FVF_Category_Container();
  196. if (fvf_category) {
  197. fvf_category->Change_Polygon_Renderer_Texture(PolygonRendererList,texture,new_texture,pass,stage);
  198. }
  199. }
  200. }
  201. }
  202. void MeshModelClass::Replace_VertexMaterial(VertexMaterialClass* vmat,VertexMaterialClass* new_vmat)
  203. {
  204. WWASSERT(vmat);
  205. WWASSERT(new_vmat);
  206. for (int pass=0;pass<Get_Pass_Count();++pass) {
  207. if (Has_Material_Array(pass)) {
  208. for (int i=0;i<Get_Vertex_Count();++i) {
  209. if (Peek_Material(i,pass)==vmat) {
  210. Set_Material(i,new_vmat,pass);
  211. }
  212. }
  213. }
  214. else {
  215. if (Peek_Single_Material(pass)==vmat) {
  216. Set_Single_Material(new_vmat,pass);
  217. }
  218. }
  219. // If this mesh model has been initialized for rendering we need to tell the rendering
  220. // system to change texturing as well.
  221. DX8FVFCategoryContainer* fvf_category=Peek_FVF_Category_Container();
  222. if (fvf_category) {
  223. fvf_category->Change_Polygon_Renderer_Material(PolygonRendererList,vmat,new_vmat,pass);
  224. }
  225. }
  226. }
  227. DX8FVFCategoryContainer* MeshModelClass::Peek_FVF_Category_Container()
  228. {
  229. if (PolygonRendererList.Is_Empty()) return NULL;
  230. DX8PolygonRendererClass* polygon_renderer=PolygonRendererList.Get_Head();
  231. WWASSERT(polygon_renderer);
  232. DX8TextureCategoryClass* texture_category=polygon_renderer->Get_Texture_Category();
  233. WWASSERT(texture_category);
  234. DX8FVFCategoryContainer* fvf_category=texture_category->Get_Container();
  235. WWASSERT(fvf_category);
  236. return fvf_category;
  237. }
  238. void MeshModelClass::Shadow_Render(SpecialRenderInfoClass & rinfo,const Matrix3D & tm,const HTreeClass * htree)
  239. {
  240. if (rinfo.BWRenderer != NULL) {
  241. if (_TempTransformedVertexBuffer.Length() < VertexCount) _TempTransformedVertexBuffer.Resize(VertexCount);
  242. Vector4* transf_ptr=&(_TempTransformedVertexBuffer[0]);
  243. get_deformed_screenspace_vertices(transf_ptr,rinfo,tm,htree);
  244. Vector2* tptr = reinterpret_cast<Vector2 *>(transf_ptr);
  245. Vector4* optr = transf_ptr;
  246. for (int a=0;a<VertexCount;++a,++optr) *tptr++=Vector2((*optr)[0],-(*optr)[1]);
  247. rinfo.BWRenderer->Set_Vertex_Locations(reinterpret_cast<Vector2*>(transf_ptr),VertexCount);
  248. rinfo.BWRenderer->Render_Triangles(reinterpret_cast<const unsigned long*>(Poly->Get_Array()),PolyCount*3);
  249. return;
  250. }
  251. }
  252. void MeshModelClass::Make_Geometry_Unique()
  253. {
  254. WWASSERT(Vertex);
  255. ShareBufferClass<Vector3> * unique_verts = NEW_REF(ShareBufferClass<Vector3>,(*Vertex));
  256. REF_PTR_SET(Vertex,unique_verts);
  257. REF_PTR_RELEASE(unique_verts);
  258. ShareBufferClass<Vector3> * norms = NEW_REF(ShareBufferClass<Vector3>,(*VertexNorm));
  259. REF_PTR_SET(VertexNorm,norms);
  260. REF_PTR_RELEASE(norms);
  261. #if (!OPTIMIZE_PLANEEQ_RAM)
  262. ShareBufferClass<Vector4> * peq = NEW_REF(ShareBufferClass<Vector4>,(*PlaneEq, "MeshModelClass::PlaneEq"));
  263. REF_PTR_SET(PlaneEq,peq);
  264. REF_PTR_RELEASE(peq);
  265. #endif
  266. }
  267. void MeshModelClass::Make_UV_Array_Unique(int pass,int stage)
  268. {
  269. CurMatDesc->Make_UV_Array_Unique(pass,stage);
  270. }
  271. void MeshModelClass::Make_Color_Array_Unique(int array_index)
  272. {
  273. CurMatDesc->Make_Color_Array_Unique(array_index);
  274. }
  275. void MeshModelClass::Enable_Alternate_Material_Description(bool onoff)
  276. {
  277. if ((onoff == true) && (AlternateMatDesc != NULL)) {
  278. if (CurMatDesc != AlternateMatDesc) {
  279. CurMatDesc = AlternateMatDesc;
  280. if (Get_Flag(SORT) && WW3D::Is_Munge_Sort_On_Load_Enabled())
  281. compute_static_sort_levels();
  282. if (WW3D::Is_Overbright_Modify_On_Load_Enabled())
  283. modify_for_overbright();
  284. // TODO: Invalidate just this meshes DX8 data!!!
  285. TheDX8MeshRenderer.Invalidate();
  286. }
  287. } else {
  288. if (CurMatDesc != DefMatDesc) {
  289. CurMatDesc = DefMatDesc;
  290. if (Get_Flag(SORT) && WW3D::Is_Munge_Sort_On_Load_Enabled())
  291. compute_static_sort_levels();
  292. if (WW3D::Is_Overbright_Modify_On_Load_Enabled())
  293. modify_for_overbright();
  294. // TODO: Invalidate this meshes DX8 data!!!
  295. TheDX8MeshRenderer.Invalidate();
  296. }
  297. }
  298. }
  299. bool MeshModelClass::Is_Alternate_Material_Description_Enabled(void)
  300. {
  301. return CurMatDesc == AlternateMatDesc;
  302. }
  303. /*
  304. void MeshModelClass::Process_Texture_Reduction(void)
  305. {
  306. MatInfo->Process_Texture_Reduction();
  307. }
  308. */
  309. bool MeshModelClass::Needs_Vertex_Normals(void)
  310. {
  311. if (Get_Flag(MeshModelClass::PRELIT_MASK) == 0) {
  312. return true;
  313. }
  314. return CurMatDesc->Do_Mappers_Need_Normals();
  315. }
  316. struct TriangleSide
  317. {
  318. Vector3 loc1;
  319. Vector3 loc2;
  320. TriangleSide(const Vector3& l1,const Vector3& l2)
  321. {
  322. int i1=*(int*)&l1[0];
  323. i1=37*i1+*(int*)&l1[1];
  324. i1=37*i1+*(int*)&l1[2];
  325. int i2=*(int*)&l2[0];
  326. i2=37*i2+*(int*)&l2[1];
  327. i2=37*i2+*(int*)&l2[2];
  328. if (i1<i2) {
  329. loc1=l1;
  330. loc2=l2;
  331. }
  332. else {
  333. loc2=l1;
  334. loc1=l2;
  335. }
  336. }
  337. TriangleSide() {}
  338. bool operator== (const TriangleSide& s)
  339. {
  340. unsigned i=*(unsigned*)&loc1[0]^*(unsigned*)&s.loc1[0];
  341. i|=*(unsigned*)&loc1[1]^*(unsigned*)&s.loc1[1];
  342. i|=*(unsigned*)&loc1[2]^*(unsigned*)&s.loc1[2];
  343. i|=*(unsigned*)&loc2[0]^*(unsigned*)&s.loc2[0];
  344. i|=*(unsigned*)&loc2[1]^*(unsigned*)&s.loc2[1];
  345. i|=*(unsigned*)&loc2[2]^*(unsigned*)&s.loc2[2];
  346. return !i;
  347. }
  348. };
  349. // Get_Hash_Value specialization for Vector3.
  350. template <> inline unsigned int HashTemplateKeyClass<Vector3>::Get_Hash_Value(const Vector3& location)
  351. {
  352. const unsigned char* buffer=(const unsigned char*)&location;
  353. unsigned int hval=0;
  354. for (unsigned int a=0;a<sizeof(Vector3);++a) {
  355. hval+=37*hval+buffer[a];
  356. }
  357. return hval;
  358. }
  359. // Get_Hash_Value specialization for TriangleSide.
  360. template <> inline unsigned int HashTemplateKeyClass<TriangleSide>::Get_Hash_Value(const TriangleSide& side)
  361. {
  362. const unsigned char* buffer=(const unsigned char*)&side;
  363. unsigned int hval=0;
  364. for (unsigned int a=0;a<sizeof(TriangleSide);++a) {
  365. hval+=37*hval+buffer[a];
  366. }
  367. return hval;
  368. }
  369. struct SideIndexInfo
  370. {
  371. unsigned short vidx1;
  372. unsigned short vidx2;
  373. unsigned polygon_index;
  374. SideIndexInfo() {}
  375. SideIndexInfo(int i) { WWASSERT(0); }
  376. };
  377. HashTemplateClass<Vector3, unsigned> LocationHash;
  378. HashTemplateClass<Vector3, unsigned> DuplicateLocationHash;
  379. HashTemplateClass<TriangleSide,SideIndexInfo> SideHash;
  380. // ----------------------------------------------------------------------------
  381. //
  382. // Allocate a gap-filler object. The constructor allocates memory for the
  383. // maximum possible amount of gap polygons, which is quite much. After all
  384. // the gap polygons have been added to the arrays, Shrink_Arrays() should
  385. // be called to free up all unneeded memory.
  386. //
  387. // ----------------------------------------------------------------------------
  388. GapFillerClass::GapFillerClass(MeshModelClass* mmc_) : mmc(NULL), PolygonCount(0)
  389. {
  390. //DMS - We cannot take a reference to the mesh model here! This is because the mesh model
  391. // class OWNS the GapFiller class (allocated via NEW). If we take a reference here, there
  392. // will be an extra reference on the parent object, which will result in the parent object
  393. // not being destroyed.
  394. //
  395. // REF_PTR_SET(mmc,mmc_);
  396. mmc = mmc_;
  397. ArraySize=mmc->Get_Polygon_Count()*6; // Each side of each triangle can have 2 polygons added, in the worst case
  398. PolygonArray=W3DNEWARRAY TriIndex[ArraySize];
  399. for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
  400. for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
  401. if (mmc->Has_Texture_Array(pass,stage)) {
  402. TextureArray[pass][stage]=W3DNEWARRAY TextureClass*[ArraySize];
  403. }
  404. else TextureArray[pass][stage]=NULL;
  405. }
  406. if (mmc->Has_Material_Array(pass)) {
  407. MaterialArray[pass]=W3DNEWARRAY VertexMaterialClass*[ArraySize];
  408. }
  409. else MaterialArray[pass]=NULL;
  410. if (mmc->Has_Shader_Array(pass)) {
  411. ShaderArray[pass]=W3DNEWARRAY ShaderClass[ArraySize];
  412. }
  413. else ShaderArray[pass]=NULL;
  414. }
  415. }
  416. GapFillerClass::GapFillerClass(const GapFillerClass& that) : mmc(NULL), PolygonCount(that.PolygonCount)
  417. {
  418. //DMS - We cannot take a reference to the mesh model here! This is because the mesh model
  419. // class OWNS the GapFiller class (allocated via NEW). If we take a reference here, there
  420. // will be an extra reference on the parent object, which will result in the parent object
  421. // not being destroyed.
  422. //
  423. // REF_PTR_SET(mmc,that.mmc);
  424. mmc = that.mmc;
  425. ArraySize=that.ArraySize;
  426. PolygonArray=W3DNEWARRAY TriIndex[ArraySize];
  427. for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
  428. for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
  429. if (that.TextureArray[pass][stage]) {
  430. TextureArray[pass][stage]=W3DNEWARRAY TextureClass*[ArraySize];
  431. for (unsigned i=0;i<PolygonCount;++i) {
  432. TextureArray[pass][stage][i]=that.TextureArray[pass][stage][i];
  433. TextureArray[pass][stage][i]->Add_Ref();
  434. }
  435. }
  436. else TextureArray[pass][stage]=NULL;
  437. }
  438. if (that.MaterialArray[pass]) {
  439. MaterialArray[pass]=W3DNEWARRAY VertexMaterialClass*[ArraySize];
  440. for (unsigned i=0;i<PolygonCount;++i) {
  441. MaterialArray[pass][i]=that.MaterialArray[pass][i];
  442. MaterialArray[pass][i]->Add_Ref();
  443. }
  444. }
  445. else MaterialArray[pass]=NULL;
  446. if (that.ShaderArray[pass]) {
  447. ShaderArray[pass]=W3DNEWARRAY ShaderClass[ArraySize];
  448. for (unsigned i=0;i<PolygonCount;++i) {
  449. ShaderArray[pass][i]=that.ShaderArray[pass][i];
  450. }
  451. }
  452. else ShaderArray[pass]=NULL;
  453. }
  454. }
  455. // ----------------------------------------------------------------------------
  456. //
  457. // Destruct gap-filler object. Release references to all textures and release
  458. // the arrays.
  459. //
  460. // ----------------------------------------------------------------------------
  461. GapFillerClass::~GapFillerClass()
  462. {
  463. delete[] PolygonArray;
  464. for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
  465. for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
  466. if (TextureArray[pass][stage]) {
  467. for (unsigned i=0;i<PolygonCount;++i) {
  468. REF_PTR_RELEASE(TextureArray[pass][stage][i]);
  469. }
  470. delete[] TextureArray[pass][stage];
  471. }
  472. }
  473. if (MaterialArray[pass]) {
  474. for (unsigned i=0;i<PolygonCount;++i) {
  475. REF_PTR_RELEASE(MaterialArray[pass][i]);
  476. }
  477. delete[] MaterialArray[pass];
  478. }
  479. delete[] ShaderArray[pass];
  480. }
  481. // DMS - Removed - See constructor for details.
  482. // REF_PTR_RELEASE(mmc);
  483. }
  484. // ----------------------------------------------------------------------------
  485. //
  486. // Add polygon to gap filler.
  487. //
  488. // ----------------------------------------------------------------------------
  489. void GapFillerClass::Add_Polygon(unsigned polygon_index,unsigned vidx1,unsigned vidx2, unsigned vidx3)
  490. {
  491. WWASSERT(PolygonCount<ArraySize);
  492. WWASSERT(vidx1!=vidx2 && vidx1!=vidx3 && vidx2!=vidx3);
  493. Vector3 loc1=mmc->Get_Vertex_Array()[vidx1];
  494. Vector3 loc2=mmc->Get_Vertex_Array()[vidx2];
  495. Vector3 loc3=mmc->Get_Vertex_Array()[vidx3];
  496. WWASSERT(loc1==loc2 || loc1==loc3 || loc2==loc3);
  497. //sdflksdjflsdkf
  498. //vidx1=mmc->Get_Polygon_Array()[polygon_index][0];
  499. //vidx2=mmc->Get_Polygon_Array()[polygon_index][1];
  500. //vidx3=mmc->Get_Polygon_Array()[polygon_index][2];
  501. PolygonArray[PolygonCount]=TriIndex(vidx1,vidx2,vidx3);
  502. for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
  503. if (mmc->Has_Shader_Array(pass)) {
  504. ShaderArray[pass][PolygonCount]=mmc->Get_Shader(polygon_index,pass);
  505. }
  506. if (mmc->Has_Material_Array(pass)) {
  507. // MaterialArray[pass][PolygonCount]=mmc->Get_Material(polygon_index,pass);
  508. MaterialArray[pass][PolygonCount]=mmc->Get_Material(mmc->Get_Polygon_Array()[polygon_index][0],pass);
  509. }
  510. for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
  511. if (mmc->Has_Texture_Array(pass,stage)) {
  512. TextureArray[pass][stage][PolygonCount]=mmc->Get_Texture(polygon_index,pass,stage);
  513. }
  514. }
  515. }
  516. PolygonCount++;
  517. }
  518. // ----------------------------------------------------------------------------
  519. //
  520. // Resize buffers to match the polygon count exatly. After this call no more
  521. // polygons can be added to the buffers.
  522. //
  523. // ----------------------------------------------------------------------------
  524. void GapFillerClass::Shrink_Buffers()
  525. {
  526. if (PolygonCount==ArraySize) return;
  527. // Shrink the polygon array
  528. TriIndex* new_polygon_array=W3DNEWARRAY TriIndex[PolygonCount];
  529. memcpy(new_polygon_array,PolygonArray,PolygonCount*sizeof(TriIndex));
  530. delete[] PolygonArray;
  531. PolygonArray=new_polygon_array;
  532. for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
  533. for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
  534. if (TextureArray[pass][stage]) {
  535. // Shrink the texture array
  536. TextureClass** new_texture_array=W3DNEWARRAY TextureClass*[PolygonCount];
  537. memcpy(new_texture_array,TextureArray[pass][stage],PolygonCount*sizeof(TextureClass*));
  538. delete[] TextureArray[pass][stage];
  539. TextureArray[pass][stage]=new_texture_array;
  540. }
  541. }
  542. if (MaterialArray[pass]) {
  543. // Shrink the material array
  544. VertexMaterialClass** new_material_array=W3DNEWARRAY VertexMaterialClass*[PolygonCount];
  545. memcpy(new_material_array,MaterialArray[pass],PolygonCount*sizeof(VertexMaterialClass*));
  546. delete[] MaterialArray[pass];
  547. MaterialArray[pass]=new_material_array;
  548. }
  549. if (ShaderArray[pass]) {
  550. // Shrink the shader array
  551. ShaderClass* new_shader_array=W3DNEWARRAY ShaderClass[PolygonCount];
  552. memcpy(new_shader_array,ShaderArray[pass],PolygonCount*sizeof(ShaderClass));
  553. delete[] ShaderArray[pass];
  554. ShaderArray[pass]=new_shader_array;
  555. }
  556. }
  557. ArraySize=PolygonCount;
  558. }
  559. // ----------------------------------------------------------------------------
  560. //
  561. // Hard edges cause gaps to n-patches meshes. This code searches for hard edges
  562. // and adds gaps filler polygons, using existing vertices.
  563. //
  564. // ----------------------------------------------------------------------------
  565. void MeshModelClass::Init_For_NPatch_Rendering()
  566. {
  567. if (!DX8Wrapper::Get_Current_Caps()->Support_NPatches()) return;
  568. if (!Get_Flag(MeshGeometryClass::ALLOW_NPATCHES)) return;
  569. if (GapFiller) return;
  570. const Vector3* locations=Get_Vertex_Array();
  571. unsigned vertex_count=Get_Vertex_Count();
  572. const TriIndex* polygon_indices=Get_Polygon_Array();
  573. unsigned polygon_count=Get_Polygon_Count();
  574. LocationHash.Remove_All();
  575. DuplicateLocationHash.Remove_All();
  576. SideHash.Remove_All();
  577. for (unsigned i=0;i<vertex_count;++i) {
  578. if (LocationHash.Exists(locations[i])) {
  579. if (!DuplicateLocationHash.Exists(locations[i])) {
  580. DuplicateLocationHash.Insert(locations[i],i);
  581. }
  582. }
  583. else {
  584. LocationHash.Insert(locations[i],i);
  585. }
  586. }
  587. for (i=0;i<polygon_count;++i) {
  588. bool duplicates[3];
  589. duplicates[0]=DuplicateLocationHash.Exists(locations[polygon_indices[i][0]]);
  590. duplicates[1]=DuplicateLocationHash.Exists(locations[polygon_indices[i][1]]);
  591. duplicates[2]=DuplicateLocationHash.Exists(locations[polygon_indices[i][2]]);
  592. if (duplicates[0] && duplicates[1]) {
  593. TriangleSide tri(locations[polygon_indices[i][0]],locations[polygon_indices[i][1]]);
  594. if (SideHash.Exists(tri)) {
  595. SideIndexInfo side_index=SideHash.Get(tri);
  596. unsigned idx1=side_index.vidx1;
  597. unsigned idx2=side_index.vidx2;
  598. unsigned idx3=polygon_indices[i][0];
  599. unsigned idx4=polygon_indices[i][1];
  600. bool diff=!(idx1^idx3)|!(idx1^idx4)|!(idx2^idx3)|!(idx2^idx4);
  601. if (!diff) {
  602. if (!GapFiller) GapFiller=W3DNEW GapFillerClass(this);
  603. GapFiller->Add_Polygon(i,idx4,idx2,idx1);
  604. GapFiller->Add_Polygon(side_index.polygon_index,idx3,idx2,idx4);
  605. }
  606. }
  607. else {
  608. SideIndexInfo side_index;
  609. side_index.vidx1=polygon_indices[i][0];
  610. side_index.vidx2=polygon_indices[i][1];
  611. side_index.polygon_index=i;
  612. SideHash.Insert(tri,side_index);
  613. }
  614. }
  615. if (duplicates[1] && duplicates[2]) {
  616. TriangleSide tri(locations[polygon_indices[i][1]],locations[polygon_indices[i][2]]);
  617. if (SideHash.Exists(tri)) {
  618. SideIndexInfo side_index=SideHash.Get(tri);
  619. unsigned idx1=side_index.vidx1;
  620. unsigned idx2=side_index.vidx2;
  621. unsigned idx3=polygon_indices[i][1];
  622. unsigned idx4=polygon_indices[i][2];
  623. bool diff=!(idx1^idx3)|!(idx1^idx4)|!(idx2^idx3)|!(idx2^idx4);
  624. if (!diff) {
  625. if (!GapFiller) GapFiller=W3DNEW GapFillerClass(this);
  626. GapFiller->Add_Polygon(i,idx4,idx2,idx1);
  627. GapFiller->Add_Polygon(side_index.polygon_index,idx3,idx2,idx4);
  628. }
  629. }
  630. else {
  631. SideIndexInfo side_index;
  632. side_index.vidx1=polygon_indices[i][1];
  633. side_index.vidx2=polygon_indices[i][2];
  634. side_index.polygon_index=i;
  635. SideHash.Insert(tri,side_index);
  636. }
  637. }
  638. if (duplicates[2] && duplicates[0]) {
  639. TriangleSide tri(locations[polygon_indices[i][2]],locations[polygon_indices[i][0]]);
  640. if (SideHash.Exists(tri)) {
  641. SideIndexInfo side_index=SideHash.Get(tri);
  642. unsigned idx1=side_index.vidx1;
  643. unsigned idx2=side_index.vidx2;
  644. unsigned idx3=polygon_indices[i][2];
  645. unsigned idx4=polygon_indices[i][0];
  646. bool diff=!(idx1^idx3)|!(idx1^idx4)|!(idx2^idx3)|!(idx2^idx4);
  647. if (!diff) {
  648. if (!GapFiller) GapFiller=W3DNEW GapFillerClass(this);
  649. GapFiller->Add_Polygon(i,idx4,idx2,idx1);
  650. GapFiller->Add_Polygon(side_index.polygon_index,idx3,idx2,idx4);
  651. }
  652. }
  653. else {
  654. SideIndexInfo side_index;
  655. side_index.vidx1=polygon_indices[i][2];
  656. side_index.vidx2=polygon_indices[i][0];
  657. side_index.polygon_index=i;
  658. SideHash.Insert(tri,side_index);
  659. }
  660. }
  661. }
  662. LocationHash.Remove_All();
  663. DuplicateLocationHash.Remove_All();
  664. SideHash.Remove_All();
  665. if (GapFiller) GapFiller->Shrink_Buffers();
  666. }