void BaseMesh::CopyMesh(BaseMesh &Copy) const { Copy._GD = _GD; Copy.Allocate(VertexCount(), FaceCount()); memcpy(Copy.Vertices(), Vertices(), sizeof(MeshVertex) * VertexCount()); memcpy(Copy.Indices(), Indices(), sizeof(DWORD) * IndexCount()); }
void BaseMesh::AppendVertices(const BaseMesh &O) { int vc = VertexCount(), ic = IndexCount(); MeshVertex *V = Vertices(), *OldV = new MeshVertex[vc]; DWORD *I = Indices(), *OldI = new DWORD[ic]; memcpy(OldV, V, vc * sizeof(MeshVertex)); memcpy(OldI, I, ic * sizeof(DWORD)); //store all the old vertices/indices Allocate(vc + O.VertexCount(), ic/3 + O.FaceCount()); //allocate space for the current vertices/indices and o's vertices/indices V = Vertices(); I = Indices(); memcpy(V, OldV, vc * sizeof(MeshVertex)); memcpy(I, OldI, ic * sizeof(DWORD)); //copy the old vertices/indices back into the mesh, memcpy(&(V[vc]), O.Vertices(), O.VertexCount() * sizeof(MeshVertex)); //copy the new vertices after the current ones, UINT oic = O.IndexCount(); const DWORD *oI = O.Indices(); for(UINT i = 0; i < oic; i++) { I[ic+i] = oI[i] + vc; //copy o's indices as well, except increasing the index by vc (since o's vertices start at vc, not 0) } delete[] OldV; delete[] OldI; }
void D3D9Mesh::CopyMesh(BaseMesh &Copy) const { Copy.SetGD(GetGD()); int VC = VertexCount(); int IC = IndexCount(); if(VC > 0 && IC > 0) { if(_Vertices == NULL) { _Mesh->LockVertexBuffer(0,(void**) &_Vertices); } if(_Indices == NULL) { _Mesh->LockIndexBuffer(0,(void**) &_Indices); } Copy.Allocate(VC, IC / 3); //allocate space in Copy memcpy(Copy.Vertices(), _Vertices, VC * sizeof(MeshVertex)); //insert our vertices into Copy memcpy(Copy.Indices(), _Indices, IC * sizeof(DWORD)); //insert our indices into Copy Unlock(); } }
void BaseMesh::CreateBox(float w, float h, float d, int refinement) { Allocate(8, 12); MeshVertex Temp(Vec3f::Origin, Vec3f::Origin, RGBColor::White, Vec2f::Origin); int i,vc=VertexCount(),ic=IndexCount(); MeshVertex *V = Vertices(); DWORD *I = Indices(); for(i=0;i<8;i++) { Temp.Pos = Vec3f(CubeVData[i][0],CubeVData[i][1],CubeVData[i][2]); V[i] = Temp; ///load the vertices } for(i=0;i<12;i++) { I[i*3+0] = CubeIData[i][0]; I[i*3+1] = CubeIData[i][1]; I[i*3+2] = CubeIData[i][2]; //load the triangles } for(i=0;i<refinement;i++) { TwoPatch(); //refine the requested number of times } Stretch(Vec3f(0.5f*w, 0.5f*h, 0.5f*d)); //stretch to the requested dimensions GenerateNormals(); }
void BaseMesh::GenerateNormals() { UINT vc = VertexCount(), ic = IndexCount(); MeshVertex *V = Vertices(); DWORD *I = Indices(); Vec3f V1, V2, Normal; for(UINT i = 0; i < vc; i++) { V[i].Normal = Vec3f::Origin; //zero each normal } for(UINT i = 0; i < ic; i += 3) //for every triangle { V1 = V[I[i+2]].Pos - V[I[i+0]].Pos; V2 = V[I[i+1]].Pos - V[I[i+0]].Pos; Normal = Vec3f::Cross(V1, V2); //compute the triangle normal V[I[i+0]].Normal += Normal; V[I[i+1]].Normal += Normal; V[I[i+2]].Normal += Normal; //each adjacent vertex adds the triangle normal to its summed normal } NormalizeNormals(); }
void BaseMesh::WeldVertices(float Epsilon, Vector<UINT> &OldToNewMapping) { PointSet MyPoints; MyPoints.LoadFromMesh(*this); KDTree3 &Tree = MyPoints.KDTree(); UINT VC = VertexCount(), IC = IndexCount(); MeshVertex *V = Vertices(); DWORD *I = Indices(); OldToNewMapping.ReSize(VC); OldToNewMapping.Clear(VC); Vector<UINT> NNResult; //MeshVertex *VStorage = new MeshVertex[VC]; for(UINT VertexIndex = 0; VertexIndex < VC; VertexIndex++) { Vec3f Pos = V[VertexIndex].Pos; Tree.WithinDistance(Pos, Epsilon, NNResult); bool MatchFound = false; //VStorage[VertexIndex] = V[VertexIndex]; for(UINT ResultIndex = 0; ResultIndex < NNResult.Length() && !MatchFound; ResultIndex++) { UINT CurIndex = NNResult[ResultIndex]; if(OldToNewMapping[CurIndex] != VC) { MatchFound = true; OldToNewMapping[VertexIndex] = CurIndex; } } if(!MatchFound) { OldToNewMapping[VertexIndex] = VertexIndex; } } //DWORD *IStorage = new DWORD[IC]; for(UINT IndexIndex = 0; IndexIndex < IC; IndexIndex++) { I[IndexIndex] = OldToNewMapping[UINT(I[IndexIndex])]; } //Allocate( //delete[] VStorage; Vector<UINT> SecondMapping, SplitToUnsplit = OldToNewMapping; CleanVerticesAndTriangles(SecondMapping); for(UINT VertexIndex = 0; VertexIndex < VC; VertexIndex++) { OldToNewMapping[VertexIndex] = SecondMapping[SplitToUnsplit[VertexIndex]]; } }
void BaseMesh::UnIndex() { int i,vc=VertexCount(),ic=IndexCount(); MeshVertex *V = Vertices(),*OldV = new MeshVertex[vc]; DWORD *I = Indices(),*OldI = new DWORD[ic]; //create space for all the old vertices and indices memcpy(OldV, V, vc * sizeof(MeshVertex)); memcpy(OldI, I, ic * sizeof(DWORD)); //copy all the old verticse and indices for storage Allocate(ic, ic/3); //allocate space for the new vertices/indices vc=VertexCount(); ic=IndexCount(); V = Vertices(); I = Indices(); for(i=0;i<vc;i++) { V[i] = OldV[OldI[i]]; //load the new vertex array I[i] = i; //the new indices are trivial; we just take every triplet in the vertex array directly. } delete[] OldV; delete[] OldI; //free up the storage }
void BaseBufferRenderBatch::AddNodeToBuffer(uint& refVertexIndex, uint& refIndexIndex, IRenderable& node) { auto mesh = node.Mesh(); const Matrix4& newMatrix = node.WorldMatrix(); mesh->AddToVertexBufferObject(mVertexBufferObject, refVertexIndex, newMatrix); mesh->AddToNormalBufferObject(mNormalBufferObject, refVertexIndex, newMatrix); mesh->AddToTexCoordBufferObject(mTexcoordBufferObject, refVertexIndex); mesh->AddToColorBufferObject(mColorBufferObject, refVertexIndex, node.WorldColor()); mesh->AddToIndexBufferObject(mIndexBufferObject, refVertexIndex, refIndexIndex); uintp vertexCount = mesh->VertexCount(); uintp indexCount = mesh->IndexCount(); node.SetBatch(this, refVertexIndex, (uint)vertexCount, refIndexIndex, (uint)indexCount); refVertexIndex += (uint)vertexCount; refIndexIndex += (uint)indexCount; RenderingStatics::Instance().IncreaseChangedNodeCount(); }
void BaseMesh::CreateSphere(float radius, int refinement) { //allocate space for the icosahedron Allocate(12, 20); MeshVertex Temp(Vec3f::Origin, Vec3f::Origin, RGBColor::White, Vec2f::Origin); int i,vc=VertexCount(),ic=IndexCount(); MeshVertex *V = Vertices(); DWORD *I = Indices(); for(i=0;i<12;i++) { Temp.Pos = Vec3f(IcosahedronVData[i][0],IcosahedronVData[i][1],IcosahedronVData[i][2]); V[i] = Temp; //load the icosahedron vertices } for(i=0;i<20;i++) { I[i*3+0] = IcosahedronIData[i][1]; I[i*3+1] = IcosahedronIData[i][0]; I[i*3+2] = IcosahedronIData[i][2]; //load the icosahedron indices } for(i=0;i<refinement;i++) TwoPatch(); //refine the specified number of times vc=VertexCount(); V = Vertices(); for(i=0;i<vc;i++) { V[i].Pos = Vec3f::Normalize(V[i].Pos); V[i].Pos *= radius; //project all the points to lie on a sphere of the specified radius } GenerateNormals(); //generate normals SetColor(RGBColor::White); }
void BaseBufferRenderBatch::UpdateNodeToBuffer(uint& refVertexIndex, uint& refIndexIndex, IRenderable& node, RenderableChangedFlags changedFlags) { auto mesh = node.Mesh(); if (MEDUSA_FLAG_HAS(changedFlags,RenderableChangedFlags::NewVertex)) { const Matrix4& newMatrix = node.WorldMatrix(); mesh->AddToVertexBufferObject(mVertexBufferObject, refVertexIndex, newMatrix); } if (MEDUSA_FLAG_HAS(changedFlags, RenderableChangedFlags::NewNormal)) { const Matrix4& newMatrix = node.WorldMatrix(); mesh->AddToNormalBufferObject(mNormalBufferObject, refVertexIndex, newMatrix); } if (MEDUSA_FLAG_HAS(changedFlags, RenderableChangedFlags::NewTexCoord)) { mesh->AddToTexCoordBufferObject(mTexcoordBufferObject, refVertexIndex); } if (MEDUSA_FLAG_HAS(changedFlags, RenderableChangedFlags::NewColor)) { mesh->AddToColorBufferObject(mColorBufferObject, refVertexIndex, node.WorldColor()); } if (MEDUSA_FLAG_HAS(changedFlags, RenderableChangedFlags::NewIndex)) { mesh->AddToIndexBufferObject(mIndexBufferObject, refVertexIndex, refIndexIndex); } uintp vertexCount = mesh->VertexCount(); uintp indexCount = mesh->IndexCount(); node.SetBatch(this, refVertexIndex, (uint)vertexCount, refIndexIndex, (uint)indexCount); refVertexIndex += (uint)vertexCount; refIndexIndex += (uint)indexCount; RenderingStatics::Instance().IncreaseChangedNodeCount(); }
VarRef *VarRefParseFromNamespaceAndScope(const char *qualified_name, const char *_ns, const char *_scope, char ns_separator, char scope_separator) { char *ns = NULL; const char *indices_start = strchr(qualified_name, '['); const char *scope_start = strchr(qualified_name, ns_separator); if (scope_start && (!indices_start || scope_start < indices_start)) { ns = xstrndup(qualified_name, scope_start - qualified_name); scope_start++; } else { scope_start = qualified_name; } char *scope = NULL; const char *lval_start = strchr(scope_start, scope_separator); if (lval_start && (!indices_start || lval_start < indices_start)) { lval_start++; scope = xstrndup(scope_start, lval_start - scope_start - 1); } else { lval_start = scope_start; } char *lval = NULL; char **indices = NULL; size_t num_indices = 0; if (indices_start) { indices_start++; lval = xstrndup(lval_start, indices_start - lval_start - 1); assert("Index brackets in variable expression did not balance" && IndexBracketsBalance(indices_start - 1)); num_indices = IndexCount(indices_start - 1); indices = xmalloc(num_indices * sizeof(char *)); Buffer *buf = BufferNew(); size_t cur_index = 0; for (const char *c = indices_start; *c != '\0'; c++) { if (*c == '[') { cur_index++; } else if (*c == ']') { indices[cur_index] = xstrdup(BufferData(buf)); BufferZero(buf); } else { BufferAppend(buf, c, sizeof(char)); } } BufferDestroy(&buf); } else { lval = xstrdup(lval_start); } assert(lval); if (!scope && !_scope) { assert(ns == NULL && "A variable missing a scope should not have a namespace"); } VarRef *ref = xmalloc(sizeof(VarRef)); ref->ns = ns ? ns : (_ns ? xstrdup(_ns) : NULL); ref->scope = scope ? scope : (_scope ? xstrdup(_scope) : NULL); ref->lval = lval; ref->indices = indices; ref->num_indices = num_indices; ref->hash = VarRefHash(ref); return ref; }
void BaseMesh::Split(float (*PositionFunction) (Vec3f &), BaseMesh &M1, BaseMesh &M2) { int i,vc=VertexCount(),ic=IndexCount(); MeshVertex *V = Vertices(); DWORD *I = Indices(); Vector<MeshVertex> NV1,NV2; Vector<TriMeshFace> NT1,NT2; SplitVMapper *VMap = new SplitVMapper[vc]; float Value; for(i=0;i<vc;i++) { Value = PositionFunction(V[i].Pos); if(Value < 0.0f) { VMap[i].Side = 0; VMap[i].NVMap1 = NV1.Length(); VMap[i].NVMap2 = -1; NV1.PushEnd(V[i]); } else { VMap[i].Side = 1; VMap[i].NVMap1 = -1; VMap[i].NVMap2 = NV2.Length(); NV2.PushEnd(V[i]); } } int TSide[3]; TriMeshFace Tri; int Oddball,State; for(i=0;i<ic;i+=3) { TSide[0] = VMap[I[i]].Side; TSide[1] = VMap[I[i+1]].Side; TSide[2] = VMap[I[i+2]].Side; if(TSide[0] && TSide[1] && TSide[2]) //all O2 { Tri.I[0] = VMap[I[i]].NVMap2; Tri.I[1] = VMap[I[i+1]].NVMap2; Tri.I[2] = VMap[I[i+2]].NVMap2; NT2.PushEnd(Tri); } else if(!(TSide[0] || TSide[1] || TSide[2])) //all O1 { Tri.I[0] = VMap[I[i]].NVMap1; Tri.I[1] = VMap[I[i+1]].NVMap1; Tri.I[2] = VMap[I[i+2]].NVMap1; NT1.PushEnd(Tri); } else { if(TSide[0] && TSide[1]) {Oddball = 2; State = 1;} if(TSide[0] && TSide[2]) {Oddball = 1; State = 1;} if(TSide[1] && TSide[2]) {Oddball = 0; State = 1;} if(!(TSide[0] || TSide[1])) {Oddball = 2; State = 2;} if(!(TSide[0] || TSide[2])) {Oddball = 1; State = 2;} if(!(TSide[1] || TSide[2])) {Oddball = 0; State = 2;} if(State == 1) //Add to Obj2 { if(VMap[I[i+Oddball]].NVMap2 == -1) { VMap[I[i+Oddball]].NVMap2 = NV2.Length(); NV2.PushEnd(V[I[i+Oddball]]); } Tri.I[0] = VMap[I[i]].NVMap2; Tri.I[1] = VMap[I[i+1]].NVMap2; Tri.I[2] = VMap[I[i+2]].NVMap2; NT2.PushEnd(Tri); } else { //Add to Obj1 if(VMap[I[i+Oddball]].NVMap1 == -1) { VMap[I[i+Oddball]].NVMap1 = NV1.Length(); NV1.PushEnd(V[I[i+Oddball]]); } Tri.I[0] = VMap[I[i]].NVMap1; Tri.I[1] = VMap[I[i+1]].NVMap1; Tri.I[2] = VMap[I[i+2]].NVMap1; NT1.PushEnd(Tri); } } } delete[] VMap; M1.Allocate(NV1.Length(),NT1.Length()); M2.Allocate(NV2.Length(),NT2.Length()); memcpy(M1.Vertices(), NV1.CArray(), M1.VertexCount() * sizeof(MeshVertex)); memcpy(M2.Vertices(), NV2.CArray(), M2.VertexCount() * sizeof(MeshVertex)); memcpy(M1.Indices(), NT1.CArray(), M1.IndexCount() * sizeof(DWORD)); memcpy(M2.Indices(), NT2.CArray(), M2.IndexCount() * sizeof(DWORD)); }
void BaseMesh::ClosedPlaneSplit(const Plane &P, BaseMesh &M1, BaseMesh &M2) { UINT VC = VertexCount(), IC = IndexCount(); MeshVertex *V = Vertices(); DWORD *I = Indices(); Vector<Vec3f> NewVertices[2]; Vector<TriMeshFace> NewFaces[2]; Vector<Vec2f> BoundaryVertices; Vector<UINT> BoundaryIndices[2]; Vec3f OrthogonalBasis1, OrthogonalBasis2; Vec3f::CompleteOrthonormalBasis(P.Normal(), OrthogonalBasis1, OrthogonalBasis2); PerfectSplitVMapper *VMap = new PerfectSplitVMapper[VC]; for(UINT VertexIndex = 0; VertexIndex < VC; VertexIndex++) { Vec3f Pos = V[VertexIndex].Pos; float Value = Plane::DotCoord(P, Pos); if(Value < 0.0f) { VMap[VertexIndex].Side = 0; VMap[VertexIndex].NVMap = NewVertices[0].Length(); NewVertices[0].PushEnd(Pos); } else { VMap[VertexIndex].Side = 1; VMap[VertexIndex].NVMap = NewVertices[1].Length(); NewVertices[1].PushEnd(Pos); } } for(UINT IndexIndex = 0; IndexIndex < IC; IndexIndex += 3) { int TSide[3]; TSide[0] = VMap[I[IndexIndex + 0]].Side; TSide[1] = VMap[I[IndexIndex + 1]].Side; TSide[2] = VMap[I[IndexIndex + 2]].Side; DWORD LocalTriangleM1[6], LocalTriangleM2[6]; LocalTriangleM2[0] = LocalTriangleM1[0] = VMap[I[IndexIndex + 0]].NVMap; LocalTriangleM2[1] = LocalTriangleM1[1] = VMap[I[IndexIndex + 1]].NVMap; LocalTriangleM2[2] = LocalTriangleM1[2] = VMap[I[IndexIndex + 2]].NVMap; UINT TriangleType = TSide[0] * 4 + TSide[1] * 2 + TSide[2] * 1; for(UINT EdgeIndex = 0; EdgeIndex < 3; EdgeIndex++) { if(PerfectEdges[TriangleType][EdgeIndex]) { Vec3f Vtx1 = V[I[IndexIndex + PerfectEdgeList[EdgeIndex][0]]].Pos; Vec3f Vtx2 = V[I[IndexIndex + PerfectEdgeList[EdgeIndex][1]]].Pos; Vec3f VtxIntersect = P.IntersectLine(Vtx1, Vtx2); if(!Vec3f::WithinRect(VtxIntersect, Rectangle3f::ConstructFromTwoPoints(Vtx1, Vtx2))) { VtxIntersect = (Vtx1 + Vtx2) * 0.5f; } BoundaryVertices.PushEnd(Vec2f(Vec3f::Dot(VtxIntersect, OrthogonalBasis1), Vec3f::Dot(VtxIntersect, OrthogonalBasis2))); LocalTriangleM1[3 + EdgeIndex] = NewVertices[0].Length(); BoundaryIndices[0].PushEnd(NewVertices[0].Length()); NewVertices[0].PushEnd(VtxIntersect); LocalTriangleM2[3 + EdgeIndex] = NewVertices[1].Length(); BoundaryIndices[1].PushEnd(NewVertices[1].Length()); NewVertices[1].PushEnd(VtxIntersect); } } for(UINT LocalTriangleIndex = 0; LocalTriangleIndex < 6; LocalTriangleIndex += 3) { if(M1Indices[TriangleType][LocalTriangleIndex] != -1) { TriMeshFace Tri; Tri.I[0] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 0]]; Tri.I[1] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 1]]; Tri.I[2] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 2]]; NewFaces[0].PushEnd(Tri); } if(M2Indices[TriangleType][LocalTriangleIndex] != -1) { TriMeshFace Tri; Tri.I[0] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 0]]; Tri.I[1] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 1]]; Tri.I[2] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 2]]; NewFaces[1].PushEnd(Tri); } } } #ifdef DELAUNAY_TRIANGULATOR if(BoundaryVertices.Length() > 0) { Vector<DWORD> BoundaryTriangulation; DelaunayTriangulator::Triangulate(BoundaryVertices, BoundaryTriangulation); for(UINT TriangleIndex = 0; TriangleIndex < BoundaryTriangulation.Length() / 3; TriangleIndex++) { for(UINT MeshIndex = 0; MeshIndex < 2; MeshIndex++) { TriMeshFace Tri; Vec3f V[3]; for(UINT LocalVertexIndex = 0; LocalVertexIndex < 3; LocalVertexIndex++) { Tri.I[LocalVertexIndex] = BoundaryIndices[MeshIndex][UINT(BoundaryTriangulation[TriangleIndex * 3 + LocalVertexIndex])]; V[LocalVertexIndex] = NewVertices[MeshIndex][UINT(Tri.I[LocalVertexIndex])]; } //Utility::Swap(Tri.I[0], Tri.I[1]); //if(Math::TriangleArea(V[0], V[1], V[2]) > 1e-5f) { NewFaces[MeshIndex].PushEnd(Tri); } } } } #endif delete[] VMap; M1.SetGD(GetGD()); M2.SetGD(GetGD()); M1.Allocate(NewVertices[0].Length(), NewFaces[0].Length()); M2.Allocate(NewVertices[1].Length(), NewFaces[1].Length()); for(UINT VertexIndex = 0; VertexIndex < NewVertices[0].Length(); VertexIndex++) { M1.Vertices()[VertexIndex].Pos = NewVertices[0][VertexIndex]; } for(UINT VertexIndex = 0; VertexIndex < NewVertices[1].Length(); VertexIndex++) { M2.Vertices()[VertexIndex].Pos = NewVertices[1][VertexIndex]; } if(NewFaces[0].Length() > 0) { memcpy(M1.Indices(), NewFaces[0].CArray(), M1.IndexCount() * sizeof(DWORD)); } if(NewFaces[1].Length() > 0) { memcpy(M2.Indices(), NewFaces[1].CArray(), M2.IndexCount() * sizeof(DWORD)); } }
void D3D9Mesh::GenerateAdj(DWORD *& Adj) { Adj = new DWORD[IndexCount()]; PersistentAssert(Adj != NULL, "GenerateAdj failed"); D3DAlwaysValidate(_Mesh->GenerateAdjacency(0.0f, Adj), "GenerateAdjacency"); }
UINT64 BaseMesh::Hash64() const { return Utility::Hash64((const BYTE *)Vertices(), VertexCount() * sizeof(MeshVertex)) + Utility::Hash64((const BYTE *)Indices(), IndexCount() * sizeof(DWORD)); }
void BaseMesh::TwoPatch() { Vector<MeshVertex> NewVertices; //list of new vertices in the mesh Vector<TriMeshFace> NewFaces; //list of new faces in the mesh UINT vc = VertexCount(), ic = IndexCount(); MeshVertex *V = Vertices(); DWORD *I = Indices(); Vector<MeshTwoPatchEdge>* HashVertices = new Vector<MeshTwoPatchEdge>[vc]; //HashVertices is a hash table that stores all edges incident on an edge. //a given edge's location in the hash table is HashVertices[Q], where Q is the index //of the smallest of the edge's two indices. DWORD LocalTIndices[6]; //we take each face and add 3 new vertices in the middle of each edge. //LocalTIndices represents these 6 vertices (the 3 new ones and the 3 origional ones.) //these 6 vertices then become 4 triangles that exactly match the origional triangle. DWORD VertexIndex; //the index of the vertex we're looking for MeshVertex NewVertex; //the new vertex we're going to add to the mesh TriMeshFace NewTriangle; //the new triangle we're going to add to the mesh MeshTwoPatchEdge NewEdge; //the edge we're going to add to the hash table for(UINT i = 0; i < vc; i++) { NewVertices.PushEnd(V[i]); //all old vertices will be in the new mesh } for(UINT i = 0; i < ic; i+=3) { LocalTIndices[0] = I[i+0]; LocalTIndices[1] = I[i+1]; LocalTIndices[2] = I[i+2]; //the origional 3 triangles are always in LocalTIndices //now it remains to get the vertices at the middle of each edge //if these aren't already in the mesh we just add a new vertex to the final mesh, otherwise we need to use our hash table to find //their position in the mesh and use those indices. for(UINT i2=0;i2<3;i2++) { int EdgeVtx1, EdgeVtx2; //the indices we're looking for if(i2 == 0) { EdgeVtx1 = I[i+0]; EdgeVtx2 = I[i+1]; } if(i2 == 1) { EdgeVtx1 = I[i+1]; EdgeVtx2 = I[i+2]; } if(i2 == 2) { EdgeVtx1 = I[i+0]; EdgeVtx2 = I[i+2]; } if(EdgeVtx2 < EdgeVtx1) Utility::Swap(EdgeVtx1, EdgeVtx2); //we want EdgeVtx1 to be the smallest if(SearchTwoPatchEdge(HashVertices[EdgeVtx1], VertexIndex, EdgeVtx2)) //search for the corresponding edge to see if it's already in the mesh { LocalTIndices[3+i2] = VertexIndex; //if it is we just choose the found index as our entry in LocalTIndices. No need to add another vertex to the mesh; it's already there } else { Interpolate(V[EdgeVtx1],V[EdgeVtx2],NewVertex,0.5f); //otherwise make a new vertex at the middle of the edge, NewEdge.v2 = EdgeVtx2; NewEdge.v1 = NewVertices.Length(); LocalTIndices[3+i2] = NewVertices.Length(); //this new vertex is our LocalTIndices entry HashVertices[EdgeVtx1].PushEnd(NewEdge); //we need to add it to the hash table... NewVertices.PushEnd(NewVertex); //and add it to the new mesh } } //Now we have all 6 of our LocalTIndices. This was one triangle in the origional mesh and is now 4 triangles in the new mesh. //we add those 4 new triangles now. NewTriangle.I[0] = LocalTIndices[0]; NewTriangle.I[1] = LocalTIndices[3]; NewTriangle.I[2] = LocalTIndices[5]; NewFaces.PushEnd(NewTriangle); NewTriangle.I[0] = LocalTIndices[3]; NewTriangle.I[1] = LocalTIndices[1]; NewTriangle.I[2] = LocalTIndices[4]; NewFaces.PushEnd(NewTriangle); NewTriangle.I[0] = LocalTIndices[5]; NewTriangle.I[1] = LocalTIndices[4]; NewTriangle.I[2] = LocalTIndices[2]; NewFaces.PushEnd(NewTriangle); NewTriangle.I[0] = LocalTIndices[5]; NewTriangle.I[1] = LocalTIndices[3]; NewTriangle.I[2] = LocalTIndices[4]; NewFaces.PushEnd(NewTriangle); } for(UINT i = 0; i <vc; i++) { HashVertices[i].FreeMemory(); } delete[] HashVertices; //free the hash table up Allocate(NewVertices.Length(), NewFaces.Length()); //allocate space for the new mesh (deleting the old mesh) MeshVertex *VNew = Vertices(); DWORD *INew = Indices(); vc = VertexCount(); ic = IndexCount(); for(UINT i = 0; i < vc; i++) { VNew[i] = NewVertices[i]; } for(UINT i = 0; i < ic / 3; i++) { INew[i * 3 + 0] = NewFaces[i].I[0]; INew[i * 3 + 1] = NewFaces[i].I[1]; INew[i * 3 + 2] = NewFaces[i].I[2]; } }
void D3D9Mesh::GenerateAdj(Vector<DWORD> &Adjacency) { Adjacency.Allocate(IndexCount()); D3DAlwaysValidate(_Mesh->GenerateAdjacency(0.0f, Adjacency.CArray()), "GenerateAdjacency"); }