meshmdl.cpp 26 KB

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