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::TextureSphericalMap(int variable) { int i; //spherical coordinates have two angles. This function computes //these angles for each vertex and maps these angles into tx and ty. //variable exists for the same reason as TextureMapToNormals int vc = VertexCount(); MeshVertex *V = Vertices(); Vec3f Pos; for(i=0;i<vc;i++) { if(variable == 0) Pos = Vec3f(V[i].Pos.x,V[i].Pos.y,V[i].Pos.z); if(variable == 1) Pos = Vec3f(V[i].Pos.x,V[i].Pos.z,V[i].Pos.y); V[i].TexCoord.x = (atan2f(Pos.y,Pos.x) + Math::PIf) / (2.0f * Math::PIf); V[i].TexCoord.y = 1.0f - (atan2f(Pos.z,sqrtf(Pos.y * Pos.y + Pos.x * Pos.x)) + Math::PIf / 2.0f) / Math::PIf; } }
void GeneralMesh::AppendQuadIndex() { uint indexBegin = static_cast<uint>(VertexCount()) - 4; uint indices[6] = { indexBegin, indexBegin + 1, indexBegin + 2, indexBegin + 2, indexBegin + 3, indexBegin }; AppendIndices(indices, 6); }
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::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 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::ColorNormalsGrayScale(RGBColor Color) { int i,vc = VertexCount(); MeshVertex *V = Vertices(); for(i=0;i<vc;i++) { Vec3f normal = V[i].Normal; int r = Utility::Bound(int(Math::Abs(normal.x/2.0f+0.5f)*255), 0, 255); int g = Utility::Bound(int(Math::Abs(normal.y/2.0f+0.5f)*255), 0, 255); int b = Utility::Bound(int(Math::Abs(normal.z/2.0f+0.5f)*255), 0, 255); //remap each normal's (x, y, z) to (r, g, b) const bool UseMaximumValue = false; if(UseMaximumValue) { if(g > r) r = g; if(b > r) r = b; } else { r = (r + g + b) / 3; //merge the 3 values into one value via some method } V[i].Color = RGBColor(r / 255.0f * Vec3f(Color)); } }
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::CleanVerticesAndTriangles(Vector<UINT> &OldToNewMapping) { UINT NumFaces = FaceCount(), NumVertices = VertexCount(); DWORD *I = Indices(); MeshVertex *V = Vertices(); Vector<DWORD> NewIndices; Vector<MeshVertex> NewVertices; OldToNewMapping.ReSize(NumVertices); OldToNewMapping.Clear(NumVertices); for(UINT FaceIndex = 0; FaceIndex < NumFaces; FaceIndex++) { if(I[FaceIndex * 3 + 0] != I[FaceIndex * 3 + 1] && I[FaceIndex * 3 + 1] != I[FaceIndex * 3 + 2] && I[FaceIndex * 3 + 2] != I[FaceIndex * 3 + 0]) { for(UINT i = 0; i < 3; i++) { UINT SourceIndex = I[FaceIndex * 3 + i]; if(OldToNewMapping[SourceIndex] == NumVertices) { OldToNewMapping[SourceIndex] = NewVertices.Length(); NewVertices.PushEnd(V[SourceIndex]); } NewIndices.PushEnd(OldToNewMapping[SourceIndex]); } } } 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]; } } }
void BaseMesh::RandomizeColors() { int i,vc=VertexCount(); MeshVertex *V = Vertices(); for(i=0;i<vc;i++) { V[i].Color = RGBColor::RandomColor(); } }
void BaseMesh::Translate(const Vec3f &v) { UINT vc = VertexCount(); MeshVertex *V = Vertices(); for(UINT i = 0; i < vc; i++) { V[i].Pos += v; } }
void BaseMesh::SetAlpha(BYTE Alpha) { MeshVertex *V = Vertices(); UINT vc = VertexCount(); for(UINT i = 0; i < vc; i++) { V[i].Color.a = Alpha; } }
void BaseMesh::ApplyMatrix(const Matrix4 &M) { UINT vc = VertexCount(); MeshVertex *V = Vertices(); for(UINT i = 0; i < vc; i++) { V[i].Pos = M.TransformPoint(V[i].Pos); V[i].Normal = M.TransformNormal(V[i].Normal); } }
void BaseMesh::Stretch(const Vec3f &v) { UINT vc = VertexCount(); MeshVertex *V = Vertices(); for(UINT i = 0; i < vc; i++) { V[i].Pos.x *= v.x; V[i].Pos.y *= v.y; V[i].Pos.z *= v.z; } }
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::NormalizeNormals() { UINT vc = VertexCount(); MeshVertex *V = Vertices(); for(UINT i = 0; i < vc; i++) { if(V[i].Normal.LengthSq() != 0.0f) { V[i].Normal = Vec3f::Normalize(V[i].Normal); } } }
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 BaseMesh::CullFaces(const BYTE FaceTest[]) { Vector<DWORD> NewIndices; Vector<MeshVertex> 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]; } } }
void BaseMesh::ColorNormals(float fr, float fg, float fb) { int i,vc=VertexCount(); MeshVertex *V = Vertices(); for(i=0;i<vc;i++) { Vec3f Normal = V[i].Normal; int r = int((Normal.x/2.0f+0.5f)*255*fr); int g = int((Normal.y/2.0f+0.5f)*255*fg); int b = int((Normal.z/2.0f+0.5f)*255*fb); //remap each normal's (x, y, z) to (r, g, b) V[i].Color = RGBColor(r,g,b); } }
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 BaseMesh::SetColor(RGBColor Color) { MeshVertex *V = Vertices(); UINT vc = VertexCount(); // // rgba to bgra // Color = Color.FlipBlueAndRed(); for(UINT i = 0; i < vc; i++) { V[i].Color = Color; } }
void GeneralMesh::AppendQuad(const QuadTextureNormalVertex& quad) { mVertices.Append(quad.LeftBottom.Position); mVertices.Append(quad.RightBottom.Position); mVertices.Append(quad.RightTop.Position); mVertices.Append(quad.LeftTop.Position); OnVertexChanged(4); mNormals.Append(quad.LeftBottom.Normal); mNormals.Append(quad.RightBottom.Normal); mNormals.Append(quad.RightTop.Normal); mNormals.Append(quad.LeftTop.Normal); OnNormalChanged(); mTexcoords.Append(quad.LeftBottom.Texcoord); mTexcoords.Append(quad.RightBottom.Texcoord); mTexcoords.Append(quad.RightTop.Texcoord); mTexcoords.Append(quad.LeftTop.Texcoord); OnTexcoordChanged(); mColors.Append(quad.LeftBottom.Color); if (!Math::IsEqual(quad.LeftBottom.Color.A, 1.f)) { mHasAlpha = true; } mColors.Append(quad.RightBottom.Color); if (!Math::IsEqual(quad.RightBottom.Color.A, 1.f)) { mHasAlpha = true; } mColors.Append(quad.RightTop.Color); if (!Math::IsEqual(quad.RightTop.Color.A, 1.f)) { mHasAlpha = true; } mColors.Append(quad.LeftTop.Color); if (!Math::IsEqual(quad.LeftTop.Color.A, 1.f)) { mHasAlpha = true; } OnColorChanged(); uint indexBegin = static_cast<uint>(VertexCount()) - 4; uint indices[6] = { indexBegin, indexBegin + 1, indexBegin + 2, indexBegin + 2, indexBegin + 3, indexBegin }; mIndices.AppendRange(indices, 6); OnIndexChanged(); }
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 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(); }
void BaseMesh::TextureMapToNormals(int variable) { int i,vc = VertexCount(); MeshVertex *V = Vertices(); //remap the normals into texture coordinates //there are three normal components (x, y, z) and only two texture coordinates (x, y), //so variable tells us which normal component not to map. for(i=0;i<vc;i++) { if(variable == 0) { V[i].TexCoord.x = (V[i].Normal.y + 1.0f) / 2.0f; V[i].TexCoord.y = (V[i].Normal.z + 1.0f) / 2.0f; } else if(variable == 1) { V[i].TexCoord.x = (V[i].Normal.x + 1.0f) / 2.0f; V[i].TexCoord.y = (V[i].Normal.z + 1.0f) / 2.0f; } else { V[i].TexCoord.x = (V[i].Normal.x + 1.0f) / 2.0f; V[i].TexCoord.y = (V[i].Normal.y + 1.0f) / 2.0f; } } }
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 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]; } }
//----------------------------------------------------------------------------- // Marks the dictionary as starting defining vertices for a new LOD //----------------------------------------------------------------------------- void CVertexDictionary::StartNewLOD() { m_nPrevLODCount = VertexCount(); }
UINT64 BaseMesh::Hash64() const { return Utility::Hash64((const BYTE *)Vertices(), VertexCount() * sizeof(MeshVertex)) + Utility::Hash64((const BYTE *)Indices(), IndexCount() * sizeof(DWORD)); }
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)); }