public MergeConvexFaces ( int maxVertsPerFace ) : void | ||
maxVertsPerFace | int | |
return | void |
public void MergeConvexFaces(int maxVertsPerFace)
{
for (var f = _fHead._next; f != _fHead; f = f._next)
{
// Skip faces which are outside the result
if (!f._inside)
{
continue;
}
var eCur = f._anEdge;
var vStart = eCur._Org;
while (true)
{
var eNext = eCur._Lnext;
var eSym = eCur._Sym;
if (eSym != null && eSym._Lface != null && eSym._Lface._inside)
{
// Try to merge the neighbour faces if the resulting polygons
// does not exceed maximum number of vertices.
int curNv = f.VertsCount;
int symNv = eSym._Lface.VertsCount;
if ((curNv + symNv - 2) <= maxVertsPerFace)
{
// Merge if the resulting poly is convex.
if (Geom.VertCCW(eCur._Lprev._Org, eCur._Org, eSym._Lnext._Lnext._Org) &&
Geom.VertCCW(eSym._Lprev._Org, eSym._Org, eCur._Lnext._Lnext._Org))
{
eNext = eSym._Lnext;
Delete(eSym);
eCur = null;
}
}
}
if (eCur != null && eCur._Lnext._Org == vStart)
break;
// Continue to next edge.
eCur = eNext;
}
}
}
private void OutputPolymesh(ElementType elementType, int polySize) { MeshUtils.Vertex v; MeshUtils.Face f; MeshUtils.Edge edge; int maxFaceCount = 0; int maxVertexCount = 0; int faceVerts, i; if (polySize < 3) { polySize = 3; } // Assume that the input data is triangles now. // Try to merge as many polygons as possible if (polySize > 3) { _mesh.MergeConvexFaces(_pool, polySize); } // Mark unused for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next) { v._n = Undef; } // Create unique IDs for all vertices and faces. for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next) { f._n = Undef; if (!f._inside) { continue; } if (NoEmptyPolygons) { var area = MeshUtils.FaceArea(f); if (DeterministicFloat.Abs(area) < DeterministicFloat.Epsilon) { continue; } } edge = f._anEdge; faceVerts = 0; do { v = edge._Org; if (v._n == Undef) { v._n = maxVertexCount; maxVertexCount++; } faceVerts++; edge = edge._Lnext; }while (edge != f._anEdge); Debug.Assert(faceVerts <= polySize); f._n = maxFaceCount; ++maxFaceCount; } _elementCount = maxFaceCount; if (elementType == ElementType.ConnectedPolygons) { maxFaceCount *= 2; } _elements = new int[maxFaceCount * polySize]; _vertexCount = maxVertexCount; _vertices = new ContourVertex[_vertexCount]; // Output vertices. for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next) { if (v._n != Undef) { // Store coordinate _vertices[v._n].Position = v._coords; _vertices[v._n].Data = v._data; } } // Output indices. int elementIndex = 0; for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next) { if (!f._inside) { continue; } if (NoEmptyPolygons) { var area = MeshUtils.FaceArea(f); if (DeterministicFloat.Abs(area) < DeterministicFloat.Epsilon) { continue; } } // Store polygon edge = f._anEdge; faceVerts = 0; do { v = edge._Org; _elements[elementIndex++] = v._n; faceVerts++; edge = edge._Lnext; } while (edge != f._anEdge); // Fill unused. for (i = faceVerts; i < polySize; ++i) { _elements[elementIndex++] = Undef; } // Store polygon connectivity if (elementType == ElementType.ConnectedPolygons) { edge = f._anEdge; do { _elements[elementIndex++] = GetNeighbourFace(edge); edge = edge._Lnext; } while (edge != f._anEdge); // Fill unused. for (i = faceVerts; i < polySize; ++i) { _elements[elementIndex++] = Undef; } } } }