First of all let me clear .. I am not asking about 2D mesh, to determine the winding order of 2D mesh its very easy with normal-z direction.
Second is, I am not asking any optimized algorithm, I do not worry about the time or speed, I just want to do it with my mesh.
When I triangulate a 3D object using Greedy Projection Triangulation algorithm, This problem happens. check the attached images.
If I apply 2D approaches to this model using "Calculate Signed Area" or "Cross production of AB and BC vectors of a triangle", it only solves the 2D mesh but how about a 3D mesh?
First we need to check that which triangles are in wrong winding direction in 3D mesh, then we only consider those triangles, so the issue is, how can we check that which triangles are in wrong winding direction in 3D? We can not just do with 2D approach I have tested it and but no success.
For example in case of a sphere, we can not apply 2D approach to sphere. So is there any way to solve this issue ?
Thanks.
Update # 1:
Below is the algorithm to check which edge has the same winding. It doesn't work well, I don't know why. Theoretically it should correct all the triangles but it is not correcting. For example in case of a sphere check in the attached figure. Something is wrong with it.
void GLReversedEdge(int i, int j, GLFace *temp)
{
//i'th triangle
int V1 = temp[i].v1;
int V2 = temp[i].v2;
int V3 = temp[i].v3;
//i'th triangle edges
int E1[] ={V1, V2};
int E2[] ={V2, V3};
int E3[] ={V3, V1};
//adjacent triangle
int jV1 = temp[j].v1;
int jV2 = temp[j].v2;
int jV3 = temp[j].v3;
//adjacent edges
int jE1[] ={jV1, jV2};
int jE2[] ={jV2, jV3};
int jE3[] ={jV3, jV1};
// 1st edge of adjacent triangle is checking with all edges of ith triangle
if((jE1[0] == E1[0] && jE1[1] == E1[1]) ||
(jE1[0] == E2[0] && jE1[1] == E2[1]) ||
(jE1[0] == E3[0] && jE1[1] == E3[1]))
{
temp[j].set(jV2, jV1, jV3); // 1st edges orientation is same, so reverse/swap it
}
// 2nd edge of adjacent triangle is checking with all edges of ith triangle
else if((jE2[0] == E1[0] && jE2[1] == E1[1]) ||
(jE2[0] == E2[0] && jE2[1] == E2[1]) ||
(jE2[0] == E3[0] && jE2[1] == E3[1]))
{
temp[j].set(jV1, jV3, jV2); // 2nd edges orientation is same, so reverse/swap it
}
// 3rd edge of adjacent triangle is checking with all edges of ith triangle
else if((jE3[0] == E1[0] && jE3[1] == E1[1]) ||
(jE3[0] == E2[0] && jE3[1] == E2[1]) ||
(jE3[0] == E3[0] && jE3[1] == E3[1]))
{
temp[j].set(jV3, jV2, jV1); // 3rd edges orientation is same, so reverse/swap it
}
}
void GetCorrectWindingOfMesh()
{
for(int i=0; i<nbF; i++)
{
int j1 = AdjacentTriangleToEdgeV1V2;
if(j1 >= 0) GLReversedEdge(i, j1, temp);
int j2 = AdjacentTriangleToEdgeV2V3;
if(j2 >= 0) GLReversedEdge(i, j2, temp);
int j3 = AdjacentTriangleToEdgeV3V1;
if(j3 >= 0) GLReversedEdge(i, j3, temp);
}
}
To retrieve neighboring information lets assume we have method that returns neighbor of triangle on given edge neighbor_on_egde( next_tria, edge )
.
That method can be implemented with information for each vertex in which triangles it is used. That is dictionary structure that maps vertex index to list of triangle indices. It is easily created by passing through list of triangles and setting for each triangle vertex index of triangle in right dictionary element.
Traversal is done by storing which triangles to check for orientation and which triangles are already checked. While there are triangles to check, make check on it and add it's neighbors to be checked if they weren't checked. Pseudo code looks like:
to_process = set of pairs triangle and orientation edge
initial state is one good oriented triangle with any edge on it
processed = set of processed triangles; initial empty
while to_process is not empty:
next_tria, orientation_edge = to_process.pop()
add next_tria in processed
if next_tria is not opposite oriented than orientation_edge:
change next_tria (ABC) orientation (B<->C)
for each edge (AB) in next_tria:
neighbor_tria = neighbor_on_egde( next_tria, edge )
if neighbor_tria exists and neighbor_tria not in processed:
to_process add (neighbor_tria, edge opposite oriented (BA))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With