struct MeshTwoPatchEdge {
DWORD v1, v2;
};
bool SearchTwoPatchEdge(Vector<MeshTwoPatchEdge> &List, DWORD &v1, DWORD v2)
{
for(UINT i = 0; i < List.Length(); i++)
{
if(List[i].v2 == v2) {
v1 = List[i].v1;
return true; }
}
return false;
}
void BaseMesh::TwoPatch()
{
Vector<MeshVertex> NewVertices; Vector<TriMeshFace> NewFaces;
UINT vc = VertexCount(), ic = IndexCount();
MeshVertex *V = Vertices();
DWORD *I = Indices();
Vector<MeshTwoPatchEdge>* HashVertices = new Vector<MeshTwoPatchEdge>[vc];
DWORD LocalTIndices[6];
DWORD VertexIndex; MeshVertex NewVertex; TriMeshFace NewTriangle; MeshTwoPatchEdge NewEdge;
for(UINT i = 0; i < vc; i++)
{
NewVertices.PushEnd(V[i]); }
for(UINT i = 0; i < ic; i+=3)
{
LocalTIndices[0] = I[i+0];
LocalTIndices[1] = I[i+1];
LocalTIndices[2] = I[i+2];
for(UINT i2=0;i2<3;i2++)
{
int EdgeVtx1, EdgeVtx2; 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); if(SearchTwoPatchEdge(HashVertices[EdgeVtx1], VertexIndex, EdgeVtx2)) {
LocalTIndices[3+i2] = VertexIndex; } else
{
Interpolate(V[EdgeVtx1],V[EdgeVtx2],NewVertex,0.5f); NewEdge.v2 = EdgeVtx2;
NewEdge.v1 = NewVertices.Length();
LocalTIndices[3+i2] = NewVertices.Length(); HashVertices[EdgeVtx1].PushEnd(NewEdge); NewVertices.PushEnd(NewVertex); }
}
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;
Allocate(NewVertices.Length(), NewFaces.Length());
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 BaseMesh::CleanVerticesAndTriangles()
{
Vector<UINT> OldToNewMapping;
CleanVerticesAndTriangles(OldToNewMapping);
}
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::UnIndex()
{
int i,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));
Allocate(ic, ic/3); vc=VertexCount();
ic=IndexCount();
V = Vertices();
I = Indices();
for(i=0;i<vc;i++)
{
V[i] = OldV[OldI[i]]; I[i] = i; }
delete[] OldV;
delete[] OldI; }
#ifdef USE_POINT_SET
void BaseMesh::WeldVertices(float Epsilon)
{
Vector<UINT> OldToNewMapping;
WeldVertices(Epsilon, OldToNewMapping);
CleanVerticesAndTriangles();
}
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;
for(UINT VertexIndex = 0; VertexIndex < VC; VertexIndex++)
{
Vec3f Pos = V[VertexIndex].Pos;
Tree.WithinDistance(Pos, Epsilon, NNResult);
bool MatchFound = false;
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;
}
}
for(UINT IndexIndex = 0; IndexIndex < IC; IndexIndex++)
{
I[IndexIndex] = OldToNewMapping[UINT(I[IndexIndex])];
}
Vector<UINT> SecondMapping, SplitToUnsplit = OldToNewMapping;
CleanVerticesAndTriangles(SecondMapping);
for(UINT VertexIndex = 0; VertexIndex < VC; VertexIndex++)
{
OldToNewMapping[VertexIndex] = SecondMapping[SplitToUnsplit[VertexIndex]];
}
}
#endif
void BaseMesh::Subdivide()
{
ComplexMesh EM;
EM.Load(*this);
EM.Subdivision(*this);
}
void BaseMesh::Subdivide(UINT Iterations)
{
for(UINT i = 0; i < Iterations; i++)
{
Subdivide();
}
}