meshmdl.cpp 26 KB

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