/* BaseMeshSplitting.cpp Written by Matthew Fisher BaseMesh is an abstract mesh class that defines basic mesh functionality. It also includes source for most of the manipulation (shape generation, file loading, etc.) that is possible under this generic structure. Each mesh must be associated with a graphics device before most operations can be performed. Because there are so many associated functions, they are grouped into various files. BaseMeshSplitting.cpp contains all the Split and PerfectSplit functions. */ struct SplitVMapper { unsigned char Side; int NVMap1,NVMap2; }; Plane BaseMeshPlane; float BaseMeshPlaneFunction(Vec3f &V) { return V.x * BaseMeshPlane.a + V.y * BaseMeshPlane.b + V.z * BaseMeshPlane.c + BaseMeshPlane.d; } void BaseMesh::Split(Plane &p, BaseMesh &M1, BaseMesh &M2) { BaseMeshPlane = p; Split(BaseMeshPlaneFunction, M1, M2); } void BaseMesh::Split(float (*PositionFunction) (Vec3f &), BaseMesh &M1, BaseMesh &M2) { int i,vc=VertexCount(),ic=IndexCount(); MeshVertex *V = Vertices(); DWORD *I = Indices(); Vector NV1,NV2; Vector NT1,NT2; SplitVMapper *VMap = new SplitVMapper[vc]; float Value; for(i=0;i NewVertices[2]; Vector NewFaces[2]; Vector BoundaryVertices; Vector 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 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 BaseMesh::CullFaces(const BYTE FaceTest[]) { Vector NewIndices; Vector NewVertices; UINT NumFaces = FaceCount(), NumVertices = VertexCount(); DWORD *I = Indices(); MeshVertex *V = Vertices(); for(UINT VertexIndex = 0; VertexIndex < NumVertices; VertexIndex++) { NewVertices.PushEnd(V[VertexIndex]); } for(UINT FaceIndex = 0; FaceIndex < NumFaces; FaceIndex++) { if(FaceTest[FaceIndex]) { for(UINT i = 0; i < 3; i++) { NewIndices.PushEnd(I[FaceIndex * 3 + i]); } } } Allocate(NewVertices.Length(), NewIndices.Length() / 3); NumFaces = FaceCount(); NumVertices = VertexCount(); I = Indices(); V = Vertices(); for(UINT VertexIndex = 0; VertexIndex < NumVertices; VertexIndex++) { V[VertexIndex] = NewVertices[VertexIndex]; } for(UINT FaceIndex = 0; FaceIndex < NumFaces; FaceIndex++) { for(UINT i = 0; i < 3; i++) { I[FaceIndex * 3 + i] = NewIndices[FaceIndex * 3 + i]; } } }