I have a 3D mesh and what I want to do is to draw the outline of my top 2D face, so here what I have acess to top mesh vertices and triangles indices and what i want is to order vertices so that I can draw my outline.
List<Vector3> GetSortedVerticesTest(Dictionary<CreateMesh.Faces, MeshData> mesh, Mesh mainMesh)
{
List<Vector3> borderVertices = mesh[CreateMesh.Faces.Top].vertices.Where(p => mesh[CreateMesh.Faces.other].vertices.Any(e => e == p)).ToList();
borderVertices = borderVertices.Distinct().ToList();
List<Vector3> sortedVertices = new List<Vector3>();
List<PointAngle> candidateAngles = new List<PointAngle>();
Vector3 startingPoint = borderVertices[0];
sortedVertices.Add(startingPoint);
borderVertices.Remove(startingPoint);
while (borderVertices.Count > 0)
{
List<Vector3> candidates = new List<Vector3>();
for (int i = 0; i < mesh[CreateMesh.Faces.Top].triangles.Count(); i += 3)
{
bool commonTriangle = false;
// verifie que le vertice courant est compris dans le triangle
for (int k = 0; k < 3; k++)
{
int triIndex = mesh[CreateMesh.Faces.Top].triangles[i + k];
Vector3 posToCompare = mainMesh.vertices[triIndex];
if (startingPoint == posToCompare)
{
commonTriangle = true;
}
}
if (commonTriangle)
{
for (int k = 0; k < 3; k++)
{
int triIndex = mesh[CreateMesh.Faces.Top].triangles[i + k];
Vector3 posToCompare = mainMesh.vertices[triIndex];
if (borderVertices.Contains(posToCompare))//epsilon
candidates.Add(posToCompare);
}
candidates.Remove(startingPoint);
if (candidates.Count != 0)
{
candidates.ForEach(c => candidateAngles.Add(new PointAngle { angle = Vector3.SignedAngle(c - startingPoint, transform.forward, Vector3.up), point = c }));
double min = candidateAngles.Min(kvp => kvp.angle);
var a = candidateAngles[0].point;
PointAngle pointsToKeep = new PointAngle();
pointsToKeep = candidateAngles.Where(s => s.angle == min).First();
sortedVertices.Add(pointsToKeep.point);
borderVertices.Remove(pointsToKeep.point);
print("vert coun" + borderVertices.Count);
startingPoint = pointsToKeep.point;
candidateAngles.Clear();
}
}
}
}
return sortedVertices;
}
here I m trying to get for all points candidates to get next vertice
I don't have convenient access to unity3D, to the following example will be using MeshGeometry3D. But I hope the classes are similar enough that it would be easy to translate.
This should produce a list of border edges for triangles that pass some arbitrary criteria. I have assumed that this is the actual goal you are trying to accomplish. Edges are represented as a pair of indices for the vertex-list of the mesh.
It should be possible to simply draw each edge. It should also be possible to join edges to a line-strip with some additional processing.
public static IEnumerable<(int e1, int e2)> GetBorderEdges(MeshGeometry3D mesh, Func<Vector3D, bool > triangleNormalFilter )
{
var numTriangles = mesh.TriangleIndices.Count / 3;
// use a value tuple to represent edges,
// value tuples have a default equal/getHashCode, so can be used in HashSet
// Since (1, 2) and (2, 1) are considered the same edge,
// all edges should be ordered smallest index first.
var allEdges = new HashSet<(int e1, int e2)>();
var nonBorderEdges = new HashSet<(int e1, int e2)>();
for (int i = 0; i < numTriangles; i++)
{
var normal = mesh.Normals[i];
// Only process triangles that pass some test,
// like normals pointing up (assuming normals exist)
if (triangleNormalFilter(normal))
{
// Multiply by three to get the index of the first value in the TriangleIndices list
var triangleIndex = i * 3;
foreach (var edge in GetEdges(mesh, triangleIndex))
{
// If the edge is already in allEdges, Add will return false
if (!allEdges.Add(edge))
{
// Since the edge must be part of two triangles, it is a non border edge
nonBorderEdges.Add(edge);
}
}
}
}
// Remove non border edges and return the result
allEdges.ExceptWith(nonBorderEdges);
return allEdges;
}
// return all edges for a triangle
private static (int e1, int e2)[] GetEdges(MeshGeometry3D mesh, int triangleIndex)
{
var t = triangleIndex;
var ti = mesh.TriangleIndices;
return new[]
{
CreateEdge(ti[triangleIndex], ti[t + 1]),
CreateEdge(ti[triangleIndex + 1], ti[t + 2]),
CreateEdge(ti[triangleIndex + 2], ti[t]),
};
}
// ensures edges are always created smaller index first
private static (int e1, int e2) CreateEdge(int e1, int e2)
{
if (e2 < e1)
{
return (e2, e1);
}
return (e1, e2);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.