| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : WW3D *
- * *
- * $Archive:: /Commando/Code/ww3d2/meshmdl.cpp $*
- * *
- * Author:: Greg Hjelstrom *
- * *
- * $Modtime:: 3/14/02 1:31p $*
- * *
- * $Revision:: 48 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "meshmdl.h"
- #include "matinfo.h"
- #include "aabtree.h"
- #include "htree.h"
- #include "vp.h"
- #include "visrasterizer.h"
- #include "dx8polygonrenderer.h"
- #include "bwrender.h"
- #include "camera.h"
- #include "dx8renderer.h"
- #include "hashtemplate.h"
- /*
- ** Temporary Buffers
- ** These buffers are used by the skin code for temporary storage of the deformed vertices and
- ** vertex normals.
- */
- static DynamicVectorClass<Vector3> _TempVertexBuffer;
- static DynamicVectorClass<Vector3> _TempNormalBuffer;
- static DynamicVectorClass<Vector4> _TempTransformedVertexBuffer;
- static DynamicVectorClass<unsigned long> _TempClipFlagBuffer;
- /*
- **
- ** MeshModelClass Implementation
- **
- */
- MeshModelClass::MeshModelClass(void) :
- DefMatDesc(NULL),
- AlternateMatDesc(NULL),
- CurMatDesc(NULL),
- MatInfo(NULL),
- GapFiller(NULL)
- {
- Set_Flag(DIRTY_BOUNDS,true);
- DefMatDesc = new MeshMatDescClass;
- CurMatDesc = DefMatDesc;
-
- MatInfo = NEW_REF( MaterialInfoClass, () );
-
- return ;
- }
- MeshModelClass::MeshModelClass(const MeshModelClass & that) :
- MeshGeometryClass(that),
- DefMatDesc(NULL),
- AlternateMatDesc(NULL),
- CurMatDesc(NULL),
- MatInfo(NULL),
- GapFiller(NULL),
- HasBeenInUse(false)
- {
- DefMatDesc = new MeshMatDescClass(*(that.DefMatDesc));
- if (that.AlternateMatDesc != NULL) {
- AlternateMatDesc = new MeshMatDescClass(*(that.AlternateMatDesc));
- }
- CurMatDesc = DefMatDesc;
- clone_materials(that);
- return ;
- }
- MeshModelClass::~MeshModelClass(void)
- {
- // WWDEBUG_SAY(("Note: Mesh %s was never used\n",Get_Name()));
- Reset(0,0,0);
- REF_PTR_RELEASE(MatInfo);
- if (DefMatDesc != NULL) {
- delete DefMatDesc;
- }
- if (AlternateMatDesc != NULL) {
- delete AlternateMatDesc;
- }
- return ;
- }
- MeshModelClass & MeshModelClass::operator = (const MeshModelClass & that)
- {
- if (this != &that) {
- MeshGeometryClass::operator = (that);
- *DefMatDesc = *(that.DefMatDesc);
- CurMatDesc = DefMatDesc;
- if (AlternateMatDesc != NULL) {
- delete AlternateMatDesc;
- AlternateMatDesc = NULL;
- }
- if (that.AlternateMatDesc != NULL) {
- AlternateMatDesc = new MeshMatDescClass(*(that.AlternateMatDesc));
- }
- clone_materials(that);
- if (GapFiller) {
- delete[] GapFiller;
- GapFiller=NULL;
- }
- if (that.GapFiller) GapFiller=new GapFillerClass(*that.GapFiller);
- }
- return * this;
- }
- void MeshModelClass::Reset(int polycount,int vertcount,int passcount)
- {
- Reset_Geometry(polycount,vertcount);
- // Release everything we have and reset to initial state
- MatInfo->Reset();
- DefMatDesc->Reset(polycount,vertcount,passcount);
- if (AlternateMatDesc != NULL) {
- delete AlternateMatDesc;
- AlternateMatDesc = NULL;
- }
- CurMatDesc = DefMatDesc;
- delete GapFiller;
- GapFiller=NULL;
- return ;
- }
- void MeshModelClass::Register_For_Rendering()
- {
- HasBeenInUse=true;
- //WW3D::Set_NPatches_Level(1);
- if (WW3D::Get_NPatches_Level()>1) {
- if (WW3D::Get_NPatches_Gap_Filling_Mode()!=WW3D::NPATCHES_GAP_FILLING_DISABLED) {
- Init_For_NPatch_Rendering();
- }
- else if (GapFiller) {
- delete GapFiller;
- GapFiller=NULL;
- }
- }
- else {
- if (WW3D::Get_NPatches_Gap_Filling_Mode()==WW3D::NPATCHES_GAP_FILLING_FORCE) {
- Init_For_NPatch_Rendering();
- }
- else if (GapFiller) {
- delete GapFiller;
- GapFiller=NULL;
- }
- }
- }
- void MeshModelClass::Replace_Texture(TextureClass* texture,TextureClass* new_texture)
- {
- #pragma message("gth - TEMPORARILY REMOVING Replace_Texture")
- #if 0
- WWASSERT(texture);
- WWASSERT(new_texture);
- for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
- for (int pass=0;pass<Get_Pass_Count();++pass) {
- if (Has_Texture_Array(pass,stage)) {
- for (int i=0;i<Get_Polygon_Count();++i) {
- if (Peek_Texture(i,pass,stage)==texture) {
- Set_Texture(i,new_texture,pass,stage);
- }
- }
- }
- else {
- if (Peek_Single_Texture(pass,stage)==texture) {
- Set_Single_Texture(new_texture,pass,stage);
- }
- }
- // If this mesh model has been initialized for rendering we need to tell the rendering
- // system to change texturing as well.
- DX8FVFCategoryContainer* fvf_category=Peek_FVF_Category_Container();
- if (fvf_category) {
- fvf_category->Change_Polygon_Renderer_Texture(PolygonRendererList,texture,new_texture,pass,stage);
- }
- }
- }
- #endif
- }
- void MeshModelClass::Replace_VertexMaterial(VertexMaterialClass* vmat,VertexMaterialClass* new_vmat)
- {
- #pragma message("gth - TEMPORARILY REMOVING Replace_Texture")
- #if 0
- WWASSERT(vmat);
- WWASSERT(new_vmat);
-
- for (int pass=0;pass<Get_Pass_Count();++pass) {
- if (Has_Material_Array(pass)) {
- for (int i=0;i<Get_Vertex_Count();++i) {
- if (Peek_Material(i,pass)==vmat) {
- Set_Material(i,new_vmat,pass);
- }
- }
- }
- else {
- if (Peek_Single_Material(pass)==vmat) {
- Set_Single_Material(new_vmat,pass);
- }
- }
- // If this mesh model has been initialized for rendering we need to tell the rendering
- // system to change texturing as well.
- DX8FVFCategoryContainer* fvf_category=Peek_FVF_Category_Container();
- if (fvf_category) {
- fvf_category->Change_Polygon_Renderer_Material(PolygonRendererList,vmat,new_vmat,pass);
- }
- }
- #endif
- }
- void MeshModelClass::Shadow_Render(SpecialRenderInfoClass & rinfo,const Matrix3D & tm,const HTreeClass * htree)
- {
- if (rinfo.BWRenderer != NULL) {
- if (_TempTransformedVertexBuffer.Length() < VertexCount) _TempTransformedVertexBuffer.Resize(VertexCount);
- Vector4* transf_ptr=&(_TempTransformedVertexBuffer[0]);
- get_deformed_screenspace_vertices(transf_ptr,rinfo,tm,htree);
- Vector2* tptr = reinterpret_cast<Vector2 *>(transf_ptr);
- Vector4* optr = transf_ptr;
- for (int a=0;a<VertexCount;++a,++optr) *tptr++=Vector2((*optr)[0],-(*optr)[1]);
- rinfo.BWRenderer->Set_Vertex_Locations(reinterpret_cast<Vector2*>(transf_ptr),VertexCount);
- rinfo.BWRenderer->Render_Triangles(reinterpret_cast<const unsigned long*>(Poly->Get_Array()),PolyCount*3);
- return;
- }
- }
- // Destination pointers MUST point to arrays large enough to hold all vertices
- void MeshModelClass::get_deformed_vertices(Vector3 *dst_vert,const HTreeClass * htree)
- {
- Vector3 * src_vert = Vertex->Get_Array();
- uint16 * bonelink = VertexBoneLink->Get_Array();
- for (int vi = 0; vi < Get_Vertex_Count(); vi++) {
- const Matrix3D & tm = htree->Get_Transform(bonelink[vi]);
- Matrix3D::Transform_Vector(tm, src_vert[vi], &(dst_vert[vi]));
- }
- }
- // Destination pointers MUST point to arrays large enough to hold all vertices
- void MeshModelClass::get_deformed_vertices(Vector3 *dst_vert, Vector3 *dst_norm,const HTreeClass * htree)
- {
- int vi;
- int vertex_count=Get_Vertex_Count();
- Vector3 * src_vert = Vertex->Get_Array();
- #if (OPTIMIZE_VNORMS)
- Vector3 * src_norm = (Vector3 *)Get_Vertex_Normal_Array();
- #else
- Vector3 * src_norm = VertexNorm->Get_Array();
- #endif
- uint16 * bonelink = VertexBoneLink->Get_Array();
- for (vi = 0; vi < vertex_count;) {
- const Matrix3D & tm = htree->Get_Transform(bonelink[vi]);
- // Make a copy so we can set the translation to zero
- Matrix3D mytm=tm;
- int idx=bonelink[vi];
- int cnt;
- for (cnt = vi; cnt < vertex_count; cnt++) {
- if (idx!=bonelink[cnt]) {
- break;
- }
- }
- VectorProcessorClass::Transform(dst_vert+vi,src_vert+vi,mytm,cnt-vi);
- mytm.Set_Translation(Vector3(0.0f,0.0f,0.0f));
- VectorProcessorClass::Transform(dst_norm+vi,src_norm+vi,mytm,cnt-vi);
- vi=cnt;
- }
- }
- // Destination pointer MUST point to arrays large enough to hold all vertices
- void MeshModelClass::compose_deformed_vertex_buffer(
- VertexFormatXYZNDUV2* verts,
- const Vector2* uv0,
- const Vector2* uv1,
- const unsigned* diffuse,
- const HTreeClass * htree)
- {
- int vi;
- int vertex_count=Get_Vertex_Count();
- Vector3 * src_vert = Vertex->Get_Array();
- #if (OPTIMIZE_VNORMS)
- Vector3 * src_norm = (Vector3 *)Get_Vertex_Normal_Array();
- #else
- Vector3 * src_norm = VertexNorm->Get_Array();
- #endif
- uint16 * bonelink = VertexBoneLink->Get_Array();
- for (vi = 0; vi < vertex_count;) {
- const Matrix3D & tm = htree->Get_Transform(bonelink[vi]);
- // Make a copy so we can set the translation to zero
- Matrix3D mytm=tm;
- int idx=bonelink[vi];
- int cnt;
- for (cnt = vi; cnt < vertex_count; cnt++) {
- if (idx!=bonelink[cnt]) {
- break;
- }
- }
- for (int pidx=0;pidx<cnt-vi;++pidx) {
- const Matrix3D& A=mytm;
- VertexFormatXYZNDUV2* out=verts+vi+pidx;
- const Vector3& v=*(src_vert+vi+pidx);
- out->x = (A[0][0] * v.X + A[0][1] * v.Y + A[0][2] * v.Z + A[0][3]);
- out->y = (A[1][0] * v.X + A[1][1] * v.Y + A[1][2] * v.Z + A[1][3]);
- out->z = (A[2][0] * v.X + A[2][1] * v.Y + A[2][2] * v.Z + A[2][3]);
- const Vector3& n=*(src_norm+vi+pidx);
- out->nx = (A[0][0] * n.X + A[0][1] * n.Y + A[0][2] * n.Z);
- out->ny = (A[1][0] * n.X + A[1][1] * n.Y + A[1][2] * n.Z);
- out->nz = (A[2][0] * n.X + A[2][1] * n.Y + A[2][2] * n.Z);
- if (diffuse) out->diffuse=diffuse[vi+pidx];
- else out->diffuse=0;
- if (uv0) reinterpret_cast<Vector2&>(verts[vi+pidx].u1)=uv0[vi+pidx];
- else reinterpret_cast<Vector2&>(verts[vi+pidx].u2)=Vector2(0.0f,0.0f);
- }
- vi=cnt;
- }
- }
- // Destination pointers MUST point to arrays large enough to hold all vertices
- void MeshModelClass::get_deformed_screenspace_vertices(Vector4 *dst_vert,const RenderInfoClass & rinfo,const Matrix3D & mesh_transform,const HTreeClass * htree)
- {
- Matrix4 prj = rinfo.Camera.Get_Projection_Matrix() * rinfo.Camera.Get_View_Matrix() * mesh_transform;
- Vector3 * src_vert = Vertex->Get_Array();
- int vertex_count=Get_Vertex_Count();
-
- if (Get_Flag(SKIN) && VertexBoneLink && htree) {
- uint16 * bonelink = VertexBoneLink->Get_Array();
- for (int vi = 0; vi < vertex_count;) {
- int idx=bonelink[vi];
- Matrix4 tm = prj * htree->Get_Transform(idx);
- // Count equal matrices (the vertices should be pre-sorted by matrices they use)
- for (int cnt = vi; cnt < vertex_count; cnt++) if (idx!=bonelink[cnt]) break;
- // Transform to screenspace (x,y,z,w)
- VectorProcessorClass::Transform(
- dst_vert+vi,
- src_vert+vi,
- tm,
- cnt-vi);
- vi=cnt;
- }
- } else {
- VectorProcessorClass::Transform(
- dst_vert,
- src_vert,
- prj,
- vertex_count);
- }
- }
- void MeshModelClass::Make_Geometry_Unique()
- {
- WWASSERT(Vertex);
- ShareBufferClass<Vector3> * unique_verts = NEW_REF(ShareBufferClass<Vector3>,(*Vertex));
- REF_PTR_SET(Vertex,unique_verts);
- REF_PTR_RELEASE(unique_verts);
-
- ShareBufferClass<Vector3> * norms = NEW_REF(ShareBufferClass<Vector3>,(*VertexNorm));
- REF_PTR_SET(VertexNorm,norms);
- REF_PTR_RELEASE(norms);
- #if (!OPTIMIZE_PLANEEQ_RAM)
- ShareBufferClass<Vector4> * peq = NEW_REF(ShareBufferClass<Vector4>,(*PlaneEq));
- REF_PTR_SET(PlaneEq,peq);
- REF_PTR_RELEASE(peq);
- #endif
- }
- void MeshModelClass::Make_UV_Array_Unique(int pass,int stage)
- {
- CurMatDesc->Make_UV_Array_Unique(pass,stage);
- }
- void MeshModelClass::Make_Color_Array_Unique(int array_index)
- {
- CurMatDesc->Make_Color_Array_Unique(array_index);
- }
- void MeshModelClass::Enable_Alternate_Material_Description(bool onoff)
- {
- if ((onoff == true) && (AlternateMatDesc != NULL)) {
- if (CurMatDesc != AlternateMatDesc) {
- CurMatDesc = AlternateMatDesc;
-
- if (Get_Flag(SORT) && WW3D::Is_Munge_Sort_On_Load_Enabled())
- compute_static_sort_levels();
-
- // TODO: Invalidate just this meshes DX8 data!!!
- TheDX8MeshRenderer.Invalidate();
- }
- } else {
- if (CurMatDesc != DefMatDesc) {
- CurMatDesc = DefMatDesc;
- if (Get_Flag(SORT) && WW3D::Is_Munge_Sort_On_Load_Enabled())
- compute_static_sort_levels();
- // TODO: Invalidate this meshes DX8 data!!!
- TheDX8MeshRenderer.Invalidate();
- }
- }
- }
- bool MeshModelClass::Is_Alternate_Material_Description_Enabled(void)
- {
- return CurMatDesc == AlternateMatDesc;
- }
- /*
- void MeshModelClass::Process_Texture_Reduction(void)
- {
- MatInfo->Process_Texture_Reduction();
- }
- */
- bool MeshModelClass::Needs_Vertex_Normals(void)
- {
- if (Get_Flag(MeshModelClass::PRELIT_MASK) == 0) {
- return true;
- }
- return CurMatDesc->Do_Mappers_Need_Normals();
- }
- struct TriangleSide
- {
- Vector3 loc1;
- Vector3 loc2;
- TriangleSide(const Vector3& l1,const Vector3& l2)
- {
- int i1=*(int*)&l1[0];
- i1=37*i1+*(int*)&l1[1];
- i1=37*i1+*(int*)&l1[2];
- int i2=*(int*)&l2[0];
- i2=37*i2+*(int*)&l2[1];
- i2=37*i2+*(int*)&l2[2];
- if (i1<i2) {
- loc1=l1;
- loc2=l2;
- }
- else {
- loc2=l1;
- loc1=l2;
- }
- }
- TriangleSide() {}
- bool operator== (const TriangleSide& s)
- {
- unsigned i=*(unsigned*)&loc1[0]^*(unsigned*)&s.loc1[0];
- i|=*(unsigned*)&loc1[1]^*(unsigned*)&s.loc1[1];
- i|=*(unsigned*)&loc1[2]^*(unsigned*)&s.loc1[2];
- i|=*(unsigned*)&loc2[0]^*(unsigned*)&s.loc2[0];
- i|=*(unsigned*)&loc2[1]^*(unsigned*)&s.loc2[1];
- i|=*(unsigned*)&loc2[2]^*(unsigned*)&s.loc2[2];
- return !i;
- }
- };
- // Get_Hash_Value specialization for Vector3.
- template <> inline unsigned int HashTemplateKeyClass<Vector3>::Get_Hash_Value(const Vector3& location)
- {
- const unsigned char* buffer=(const unsigned char*)&location;
- unsigned int hval=0;
- for (unsigned int a=0;a<sizeof(Vector3);++a) {
- hval+=37*hval+buffer[a];
- }
- return hval;
- }
- // Get_Hash_Value specialization for TriangleSide.
- template <> inline unsigned int HashTemplateKeyClass<TriangleSide>::Get_Hash_Value(const TriangleSide& side)
- {
- const unsigned char* buffer=(const unsigned char*)&side;
- unsigned int hval=0;
- for (unsigned int a=0;a<sizeof(TriangleSide);++a) {
- hval+=37*hval+buffer[a];
- }
- return hval;
- }
- struct SideIndexInfo
- {
- unsigned short vidx1;
- unsigned short vidx2;
- unsigned polygon_index;
- SideIndexInfo() {}
- SideIndexInfo(int i) { WWASSERT(0); }
- };
- HashTemplateClass<Vector3, unsigned> LocationHash;
- HashTemplateClass<Vector3, unsigned> DuplicateLocationHash;
- HashTemplateClass<TriangleSide,SideIndexInfo> SideHash;
- // ----------------------------------------------------------------------------
- //
- // Allocate a gap-filler object. The constructor allocates memory for the
- // maximum possible amount of gap polygons, which is quite much. After all
- // the gap polygons have been added to the arrays, Shrink_Arrays() should
- // be called to free up all unneeded memory.
- //
- // ----------------------------------------------------------------------------
- GapFillerClass::GapFillerClass(MeshModelClass* mmc_) : mmc(NULL), PolygonCount(0)
- {
- REF_PTR_SET(mmc,mmc_);
- ArraySize=mmc->Get_Polygon_Count()*6; // Each side of each triangle can have 2 polygons added, in the worst case
- PolygonArray=new TriIndex[ArraySize];
- for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
- for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
- if (mmc->Has_Texture_Array(pass,stage)) {
- TextureArray[pass][stage]=new TextureClass*[ArraySize];
- }
- else TextureArray[pass][stage]=NULL;
- }
- if (mmc->Has_Material_Array(pass)) {
- MaterialArray[pass]=new VertexMaterialClass*[ArraySize];
- }
- else MaterialArray[pass]=NULL;
- if (mmc->Has_Shader_Array(pass)) {
- ShaderArray[pass]=new ShaderClass[ArraySize];
- }
- else ShaderArray[pass]=NULL;
- }
- }
- GapFillerClass::GapFillerClass(const GapFillerClass& that) : mmc(NULL), PolygonCount(that.PolygonCount)
- {
- REF_PTR_SET(mmc,that.mmc);
- ArraySize=that.ArraySize;
- PolygonArray=new TriIndex[ArraySize];
- for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
- for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
- if (that.TextureArray[pass][stage]) {
- TextureArray[pass][stage]=new TextureClass*[ArraySize];
- for (unsigned i=0;i<PolygonCount;++i) {
- TextureArray[pass][stage][i]=that.TextureArray[pass][stage][i];
- TextureArray[pass][stage][i]->Add_Ref();
- }
- }
- else TextureArray[pass][stage]=NULL;
- }
- if (that.MaterialArray[pass]) {
- MaterialArray[pass]=new VertexMaterialClass*[ArraySize];
- for (unsigned i=0;i<PolygonCount;++i) {
- MaterialArray[pass][i]=that.MaterialArray[pass][i];
- MaterialArray[pass][i]->Add_Ref();
- }
- }
- else MaterialArray[pass]=NULL;
- if (that.ShaderArray[pass]) {
- ShaderArray[pass]=new ShaderClass[ArraySize];
- for (unsigned i=0;i<PolygonCount;++i) {
- ShaderArray[pass][i]=that.ShaderArray[pass][i];
- }
- }
- else ShaderArray[pass]=NULL;
- }
- }
- // ----------------------------------------------------------------------------
- //
- // Destruct gap-filler object. Release references to all textures and release
- // the arrays.
- //
- // ----------------------------------------------------------------------------
- GapFillerClass::~GapFillerClass()
- {
- delete[] PolygonArray;
- for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
- for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
- if (TextureArray[pass][stage]) {
- for (unsigned i=0;i<PolygonCount;++i) {
- REF_PTR_RELEASE(TextureArray[pass][stage][i]);
- }
- delete[] TextureArray[pass][stage];
- }
- }
- if (MaterialArray[pass]) {
- for (unsigned i=0;i<PolygonCount;++i) {
- REF_PTR_RELEASE(MaterialArray[pass][i]);
- }
- delete[] MaterialArray[pass];
- }
- delete[] ShaderArray[pass];
- }
- REF_PTR_RELEASE(mmc);
- }
- // ----------------------------------------------------------------------------
- //
- // Add polygon to gap filler.
- //
- // ----------------------------------------------------------------------------
- void GapFillerClass::Add_Polygon(unsigned polygon_index,unsigned vidx1,unsigned vidx2, unsigned vidx3)
- {
- WWASSERT(PolygonCount<ArraySize);
- WWASSERT(vidx1!=vidx2 && vidx1!=vidx3 && vidx2!=vidx3);
- Vector3 loc1=mmc->Get_Vertex_Array()[vidx1];
- Vector3 loc2=mmc->Get_Vertex_Array()[vidx2];
- Vector3 loc3=mmc->Get_Vertex_Array()[vidx3];
- WWASSERT(loc1==loc2 || loc1==loc3 || loc2==loc3);
- //sdflksdjflsdkf
- //vidx1=mmc->Get_Polygon_Array()[polygon_index][0];
- //vidx2=mmc->Get_Polygon_Array()[polygon_index][1];
- //vidx3=mmc->Get_Polygon_Array()[polygon_index][2];
- PolygonArray[PolygonCount]=TriIndex(vidx1,vidx2,vidx3);
- for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
- if (mmc->Has_Shader_Array(pass)) {
- ShaderArray[pass][PolygonCount]=mmc->Get_Shader(polygon_index,pass);
- }
- if (mmc->Has_Material_Array(pass)) {
- // MaterialArray[pass][PolygonCount]=mmc->Get_Material(polygon_index,pass);
- MaterialArray[pass][PolygonCount]=mmc->Get_Material(mmc->Get_Polygon_Array()[polygon_index][0],pass);
- }
- for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
- if (mmc->Has_Texture_Array(pass,stage)) {
- TextureArray[pass][stage][PolygonCount]=mmc->Get_Texture(polygon_index,pass,stage);
- }
- }
- }
- PolygonCount++;
- }
- // ----------------------------------------------------------------------------
- //
- // Resize buffers to match the polygon count exatly. After this call no more
- // polygons can be added to the buffers.
- //
- // ----------------------------------------------------------------------------
- void GapFillerClass::Shrink_Buffers()
- {
- if (PolygonCount==ArraySize) return;
- // Shrink the polygon array
- TriIndex* new_polygon_array=new TriIndex[PolygonCount];
- memcpy(new_polygon_array,PolygonArray,PolygonCount*sizeof(TriIndex));
- delete[] PolygonArray;
- PolygonArray=new_polygon_array;
- for (int pass=0;pass<mmc->Get_Pass_Count();++pass) {
- for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
- if (TextureArray[pass][stage]) {
- // Shrink the texture array
- TextureClass** new_texture_array=new TextureClass*[PolygonCount];
- memcpy(new_texture_array,TextureArray[pass][stage],PolygonCount*sizeof(TextureClass*));
- delete[] TextureArray[pass][stage];
- TextureArray[pass][stage]=new_texture_array;
- }
- }
- if (MaterialArray[pass]) {
- // Shrink the material array
- VertexMaterialClass** new_material_array=new VertexMaterialClass*[PolygonCount];
- memcpy(new_material_array,MaterialArray[pass],PolygonCount*sizeof(VertexMaterialClass*));
- delete[] MaterialArray[pass];
- MaterialArray[pass]=new_material_array;
- }
- if (ShaderArray[pass]) {
- // Shrink the shader array
- ShaderClass* new_shader_array=new ShaderClass[PolygonCount];
- memcpy(new_shader_array,ShaderArray[pass],PolygonCount*sizeof(ShaderClass));
- delete[] ShaderArray[pass];
- ShaderArray[pass]=new_shader_array;
- }
- }
- ArraySize=PolygonCount;
- }
- // ----------------------------------------------------------------------------
- //
- // Hard edges cause gaps to n-patches meshes. This code searches for hard edges
- // and adds gaps filler polygons, using existing vertices.
- //
- // ----------------------------------------------------------------------------
- void MeshModelClass::Init_For_NPatch_Rendering()
- {
- if (GapFiller) return;
- const Vector3* locations=Get_Vertex_Array();
- unsigned vertex_count=Get_Vertex_Count();
- const TriIndex* polygon_indices=Get_Polygon_Array();
- unsigned polygon_count=Get_Polygon_Count();
- LocationHash.Remove_All();
- DuplicateLocationHash.Remove_All();
- SideHash.Remove_All();
- for (unsigned i=0;i<vertex_count;++i) {
- if (LocationHash.Exists(locations[i])) {
- if (!DuplicateLocationHash.Exists(locations[i])) {
- DuplicateLocationHash.Insert(locations[i],i);
- }
- }
- else {
- LocationHash.Insert(locations[i],i);
- }
- }
- for (i=0;i<polygon_count;++i) {
- bool duplicates[3];
- duplicates[0]=DuplicateLocationHash.Exists(locations[polygon_indices[i][0]]);
- duplicates[1]=DuplicateLocationHash.Exists(locations[polygon_indices[i][1]]);
- duplicates[2]=DuplicateLocationHash.Exists(locations[polygon_indices[i][2]]);
- if (duplicates[0] && duplicates[1]) {
- TriangleSide tri(locations[polygon_indices[i][0]],locations[polygon_indices[i][1]]);
- if (SideHash.Exists(tri)) {
- SideIndexInfo side_index=SideHash.Get(tri);
- unsigned idx1=side_index.vidx1;
- unsigned idx2=side_index.vidx2;
- unsigned idx3=polygon_indices[i][0];
- unsigned idx4=polygon_indices[i][1];
- bool diff=!(idx1^idx3)|!(idx1^idx4)|!(idx2^idx3)|!(idx2^idx4);
- if (!diff) {
- if (!GapFiller) GapFiller=new GapFillerClass(this);
- GapFiller->Add_Polygon(i,idx4,idx2,idx1);
- GapFiller->Add_Polygon(side_index.polygon_index,idx3,idx2,idx4);
- }
- }
- else {
- SideIndexInfo side_index;
- side_index.vidx1=polygon_indices[i][0];
- side_index.vidx2=polygon_indices[i][1];
- side_index.polygon_index=i;
- SideHash.Insert(tri,side_index);
- }
- }
- if (duplicates[1] && duplicates[2]) {
- TriangleSide tri(locations[polygon_indices[i][1]],locations[polygon_indices[i][2]]);
- if (SideHash.Exists(tri)) {
- SideIndexInfo side_index=SideHash.Get(tri);
- unsigned idx1=side_index.vidx1;
- unsigned idx2=side_index.vidx2;
- unsigned idx3=polygon_indices[i][1];
- unsigned idx4=polygon_indices[i][2];
- bool diff=!(idx1^idx3)|!(idx1^idx4)|!(idx2^idx3)|!(idx2^idx4);
- if (!diff) {
- if (!GapFiller) GapFiller=new GapFillerClass(this);
- GapFiller->Add_Polygon(i,idx4,idx2,idx1);
- GapFiller->Add_Polygon(side_index.polygon_index,idx3,idx2,idx4);
- }
- }
- else {
- SideIndexInfo side_index;
- side_index.vidx1=polygon_indices[i][1];
- side_index.vidx2=polygon_indices[i][2];
- side_index.polygon_index=i;
- SideHash.Insert(tri,side_index);
- }
- }
- if (duplicates[2] && duplicates[0]) {
- TriangleSide tri(locations[polygon_indices[i][2]],locations[polygon_indices[i][0]]);
- if (SideHash.Exists(tri)) {
- SideIndexInfo side_index=SideHash.Get(tri);
- unsigned idx1=side_index.vidx1;
- unsigned idx2=side_index.vidx2;
- unsigned idx3=polygon_indices[i][2];
- unsigned idx4=polygon_indices[i][0];
- bool diff=!(idx1^idx3)|!(idx1^idx4)|!(idx2^idx3)|!(idx2^idx4);
- if (!diff) {
- if (!GapFiller) GapFiller=new GapFillerClass(this);
- GapFiller->Add_Polygon(i,idx4,idx2,idx1);
- GapFiller->Add_Polygon(side_index.polygon_index,idx3,idx2,idx4);
- }
- }
- else {
- SideIndexInfo side_index;
- side_index.vidx1=polygon_indices[i][2];
- side_index.vidx2=polygon_indices[i][0];
- side_index.polygon_index=i;
- SideHash.Insert(tri,side_index);
- }
- }
- }
- LocationHash.Remove_All();
- DuplicateLocationHash.Remove_All();
- SideHash.Remove_All();
- if (GapFiller) GapFiller->Shrink_Buffers();
- }
|