void MeshBVH::InitSingleMesh(const BaseMesh &M, UINT triangleCountCutoff) { FreeMemory(); const MeshVertex *vertices = M.Vertices(); const UINT vertexCount = M.VertexCount(); const DWORD *indices = M.Indices(); const UINT triCount = M.FaceCount(); if(MeshBVHDebugging) Console::WriteLine("Making BVH, triCount=" + String(triCount)); _triInfo.Allocate(triCount); Vector<MeshBVHTriangleInfo*> dataPointers(triCount); for(UINT triIndex = 0; triIndex < triCount; triIndex++) { MeshBVHTriangleInfo &curTriInfo = _triInfo[triIndex]; dataPointers[triIndex] = &curTriInfo; curTriInfo.v[0] = vertices[ indices[ triIndex * 3 + 0 ] ].Pos; curTriInfo.v[1] = vertices[ indices[ triIndex * 3 + 1 ] ].Pos; curTriInfo.v[2] = vertices[ indices[ triIndex * 3 + 2 ] ].Pos; } _storage.Allocate(triCount); MeshBVHNodeConstructorInfo info; info.storage = _storage.CArray(); info.storageIndex = 0; info.triangleCountCutoff = triangleCountCutoff; _root = new MeshBVHNode(dataPointers.CArray(), dataPointers.Length(), info, 0); }
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 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 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 ComplexMesh::Dump(BaseMesh &Mesh) const { Mesh.Allocate(_Vertices.Length(),_Triangles.Length()); for(UINT i=0;i<_Vertices.Length();i++) { Mesh.Vertices()[i].Pos = _Vertices[i].Pos(); Mesh.Vertices()[i].TexCoord.x = _Vertices[i].TexCoords().x; Mesh.Vertices()[i].TexCoord.y = _Vertices[i].TexCoords().y; } for(UINT i=0;i<_Triangles.Length();i++) { Mesh.Indices()[i * 3 + 0] = _Triangles[i].GetVertex(0).Index(); Mesh.Indices()[i * 3 + 1] = _Triangles[i].GetVertex(1).Index(); Mesh.Indices()[i * 3 + 2] = _Triangles[i].GetVertex(2).Index(); } Mesh.GenerateNormals(); }
void ComplexMesh::Subdivision(BaseMesh &Mesh) { UINT VertexCount = _Vertices.Length(); UINT EdgeCount = _FullEdges.Length(); UINT TriangleCount = _Triangles.Length(); //IntPair P; Mesh.Allocate(VertexCount + EdgeCount, TriangleCount * 4); MeshVertex *V = Mesh.Vertices(); DWORD *I = Mesh.Indices(); Vector<Vec3f> NewVertexPositions(_Vertices.Length()); for(UINT VertexIndex = 0; VertexIndex < VertexCount; VertexIndex++) { V[VertexIndex].Pos = _Vertices[VertexIndex].ComputeLoopSubdivisionPos(); } for(UINT EdgeIndex = 0; EdgeIndex < EdgeCount; EdgeIndex++) { V[VertexCount + EdgeIndex].Pos = _FullEdges[EdgeIndex]->ComputeLoopSubdivisionPos(); } for(UINT i = 0; i < TriangleCount; i++) { UINT SourceI[6]; Triangle &CurTriangle = _Triangles[i]; for(UINT i2 = 0; i2 < 3; i2++) { SourceI[i2 + 0] = CurTriangle.GetVertex(i2).Index(); SourceI[i2 + 3] = VertexCount + CurTriangle.GetOtherEdge(_Triangles[i].GetVertex(i2)).Index(); } I[i * 12 + 0] = SourceI[0]; I[i * 12 + 1] = SourceI[5]; I[i * 12 + 2] = SourceI[4]; I[i * 12 + 3] = SourceI[5]; I[i * 12 + 4] = SourceI[1]; I[i * 12 + 5] = SourceI[3]; I[i * 12 + 6] = SourceI[4]; I[i * 12 + 7] = SourceI[3]; I[i * 12 + 8] = SourceI[2]; I[i * 12 + 9] = SourceI[4]; I[i * 12 + 10] = SourceI[5]; I[i * 12 + 11] = SourceI[3]; } }
void RayIntersectorKDTree::Init(const BaseMesh &M) { Console::WriteString("Building RayIntersectorKDTree..."); FreeMemory(); _VertexCount = M.VertexCount(); _TriangleCount = M.FaceCount(); Console::WriteString(String(_TriangleCount) + String(" base triangles, ")); _Vertices = new Vec3f[_VertexCount]; _Indices = new UINT[_TriangleCount * 3]; const MeshVertex *MeshVertices = M.Vertices(); const DWORD *MeshIndices = M.Indices(); for(UINT VertexIndex = 0; VertexIndex < _VertexCount; VertexIndex++) { _Vertices[VertexIndex] = MeshVertices[VertexIndex].Pos; } for(UINT IndexIndex = 0; IndexIndex < _TriangleCount * 3; IndexIndex++) { _Indices[IndexIndex] = MeshIndices[IndexIndex]; } Vector<UINT> TriangleIndices(_TriangleCount); for(UINT TriangleIndex = 0; TriangleIndex < _TriangleCount; TriangleIndex++) { TriangleIndices[TriangleIndex] = TriangleIndex; } Vector<UINT> LeafTrianglesVector; _Root = new RayIntersectorKDTreeNode(TriangleIndices, *this, 0, LeafTrianglesVector); _LeafTriangleCount = LeafTrianglesVector.Length(); _LeafTriangles = new UINT[_LeafTriangleCount]; memcpy(_LeafTriangles, LeafTrianglesVector.CArray(), sizeof(UINT) * _LeafTriangleCount); Console::WriteLine(String(_LeafTriangleCount) + String(" leaf triangles.")); }
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 ComplexMesh::Load(const BaseMesh &Mesh) { FreeMemory(); _Vertices.Allocate(Mesh.VertexCount()); _Triangles.Allocate(Mesh.FaceCount()); _HalfEdges.Allocate(Mesh.FaceCount() * 3); _FullEdges.FreeMemory(); for(UINT i = 0; i < _Vertices.Length(); i++) { _Vertices[i].Pos() = Mesh.Vertices()[i].Pos; _Vertices[i].TexCoords() = Mesh.Vertices()[i].TexCoord; _Vertices[i].Boundary() = false; _Vertices[i]._Index = i; } InitHashTable(_Vertices.Length()); for(UINT TriangleIndex = 0; TriangleIndex < _Triangles.Length(); TriangleIndex++) { Triangle &CurTriangle = _Triangles[TriangleIndex]; UINT LocalIndices[3]; LocalIndices[0] = Mesh.Indices()[TriangleIndex * 3 + 0]; LocalIndices[1] = Mesh.Indices()[TriangleIndex * 3 + 1]; LocalIndices[2] = Mesh.Indices()[TriangleIndex * 3 + 2]; CurTriangle._Index = TriangleIndex; for(UINT LocalEdgeIndex = 0; LocalEdgeIndex < 3; LocalEdgeIndex++) { Vertex *SearchV[2]; CurTriangle._HalfEdges[LocalEdgeIndex] = &_HalfEdges[TriangleIndex * 3 + LocalEdgeIndex]; CurTriangle._Vertices[LocalEdgeIndex] = &_Vertices[LocalIndices[LocalEdgeIndex]]; _HalfEdges[TriangleIndex * 3 + LocalEdgeIndex]._NextEdge = &_HalfEdges[TriangleIndex * 3 + (LocalEdgeIndex + 1) % 3]; SearchV[0] = &_Vertices[LocalIndices[(LocalEdgeIndex + 1) % 3]]; SearchV[1] = &_Vertices[LocalIndices[(LocalEdgeIndex + 2) % 3]]; if(SearchV[0]->Index() > SearchV[1]->Index()) { Utility::Swap(SearchV[0], SearchV[1]); } FullEdge &Target = FindFullEdge(SearchV); if(Target != FullEdge::NotFound) { PersistentAssert(Target.GetTriangle(1) == Triangle::Boundary, "Duplicate edge; 2-manifold criterion violated."); //PersistentAssert(Target.GetTriangle(1) == Triangle::Boundary, // String("Duplicate edge; 2-manifold criterion violated: ") + String(SearchV[0]->Index()) + String(", ") + String(SearchV[1]->Index())); _HalfEdges[TriangleIndex * 3 + LocalEdgeIndex]._AcrossEdge = &Target; Target._Triangles[1] = &CurTriangle; } else { FullEdge *NewEdge = new FullEdge; Assert(NewEdge != NULL, "Out of memory"); NewEdge->_Index = _FullEdges.Length(); NewEdge->_Triangles[0] = &CurTriangle; NewEdge->_Triangles[1] = &Triangle::Boundary; NewEdge->_Vertices[0] = SearchV[0]; NewEdge->_Vertices[1] = SearchV[1]; _HalfEdges[TriangleIndex * 3 + LocalEdgeIndex]._AcrossEdge = NewEdge; _FullEdges.PushEnd(NewEdge); HashEdge(*NewEdge); } } } for(UINT TriangleIndex = 0; TriangleIndex < _Triangles.Length(); TriangleIndex++) { Triangle &CurTriangle = _Triangles[TriangleIndex]; for(UINT AdjacentTriangleIndex = 0; AdjacentTriangleIndex < 3; AdjacentTriangleIndex++) { Triangle &AdjTriangle = CurTriangle.GetNeighboringTriangle(AdjacentTriangleIndex); } } ClearHashTable(); for(UINT i = 0; i < _FullEdges.Length(); i++) { if(_FullEdges[i]->Boundary()) { _FullEdges[i]->GetVertex(0).Boundary() = true; _FullEdges[i]->GetVertex(1).Boundary() = true; _FullEdges[i]->OrientMatchingBoundary(); } } PrepareTopology(); /*if(!Oriented()) { Orient(); } PersistentAssert(Oriented(), "Mesh not oriented");*/ }