-
-
Notifications
You must be signed in to change notification settings - Fork 186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Certain models have incorrect normals #34
Comments
I think this can be fixed easier then normal fixing, but just changing the shader to assume that the normal could be flipped as well. |
So then we should autodetect whether the normals are inverted? |
No, we just use a shader that uses both options. Recalculating normals is kinda tricky to get right (especially with broken models) |
Computing normals is fairly easy if the order of the vertices is correct, i.e. using the right-hand rule (see https://en.wikipedia.org/wiki/Normal_%28geometry%29#Uniqueness_of_the_normal). If that is the case, there are a few edge cases, such as triangles without surface area (2 or more vertices have the same coordinates), but no big hurdles. If the vertices have the wrong order that is very hard to detect, since it involves detecting which side of the triangle is on the inside, which is expensive to compute and undefined if the model is not watertight. |
@Ghostkeeper That's how the normals are calculated right now. The problem is some applications just don't keep the winding order properly at all (as with the above model) OpenSCAD also has a issue where if you make a hollow cube, the inner cube will have the winding order the wrong way around. |
Just find the highest triangle and check whether the normal according to the assumed winding order also has a positive Z component, if not, flip all normals. Highest triangle = |
So let's split this into two issues - there is a set of models for which the normals are inverted which creates the wrong overhang display. Then there is the feature request of adding a "recalculate normals" option somewhere in the UI. The first thing is a bug that needs to be solved at one point or another. The other is a feature with dubious usefulness that will not be implemented before the 15.06 final release in any case. Please make a new feature request for that in the Cura repository. Any further discussion in this issue should be about fixing the normals bug. |
FYI: Models with just all the normals 100% inverted are rare. Models with some of the normals correct, but some wrong are more common. |
Yes, it is not an easy thing to solve and I do not assume we will be able to solve it before release. |
There are two kinds of bugs - consistently incorrect winding order or inconsistenly incorrect winding order. Nobody mentioned adding an option in the UI! As @daid said, the first one is not that common, so it might be an idea to solve for incorrect winding order for all faces... This is no high priority though. |
I realise that this issue won't be fixed soon due to time constraints, but I thought of a solution that's easy to implement and (I think) quite fast to compute. Here follows an explanation. You can find inconsistencies by looking at adjacent triangles. The normal vectors of two adjacent triangles must be on the same side of the mesh. Please see this example: Here we have a geometry consisting of four vertices V1, V2, V3 and V4, and given are two normals N1 and N2, of which we know N1 is correct but would like to check N2. What we'll do is compute whether V4 lies above the plane of the other triangle (comprised of V1, V2 and V3) or below. If V4 lies above the plane (in the direction of N1), the surface is concave and the normals must point towards each other. If V4 lies below the plane (in the opposite direction of N1), the surface is convex and the normals must point away from each other. To compute whether V4 lies above or below the plane, project it onto the normal perpendicular to the plane. Conveniently, this is already known as N1: The second step is to find whether N2 is pointing towards the other triangle or away from it. To do this, project N2 onto either the line V1-V2 or the line V1-V3. It doesn't matter which. Like so: This all can be summarised in the following code: //(V4 - V1).dot(N1) finds whether V4 is above the plane through the triangle of N1 (positive) or below (negative).
//N2.dot(V1 - V2) finds whether N2 points towards V1 (positive) or away from it (negative).
//If V4 is above the triangle, N2 must point towards V1. Otherwise, it must point away.
//In other words, if proj_triangle_side is positive, proj_normal_dir must be positive. If proj_triangle_side is negative, proj_normal_dir must be negative.
//Therefore, proj_triangle_side * proj_normal_dir must be positive! If it's not, invert N2.
float proj_triangle_side = (V4 - V1).dot(N1);
float proj_normal_dir = N2.dot(V1 - V2);
float projection_product = proj_triangle_side * proj_normal_dir;
if(projection_product < 0) //Either concave and pointing away from each other, or convex and towards each other.
{
N2 *= -1; //Invert the faulty normal.
}
else if(projection_product == 0) //Coplanar surfaces.
{
N2 = N1; //Normals are the same then anyway, so take the one that's sure to be correct.
} To correct all normals, you could find an initial correct normal using @BagelOrb's suggestion, finding the highest triangle and asserting that normal to have a positive Z component. Then you can propagate the correct normal throughout the mesh, for instance with breadth-first search. This would have to be repeated for every separate component, since it must propagate via two connected vertices between the triangles (one is not enough, since the concavity or convexity could be different then!). I heard though that the implementation is currently such that all triangles are disconnected from each other (meaning that in the above example, V2 and V3 are double). This makes it hard to find two adjacent triangles at all and defeats this algorithm's purpose if that is the case... Anyway, this is just for future reference if anyone would eventually like to implement some more model correction. |
The direction of a face is implicit in the winding order of its vertices. The normal is pointing upward from the plane in which the vertices are ordered counter-clockwise. As such we can just see whether two faces are flipped the same way by checking the order on the vertices; when two connected faces have their edges in the opposite direction they are correctly flipped. @Ghostkeeper your algorithm is superfluous. |
@BagelOrb Yeah that seems like a much more elegant solution than my overthinking, if the normals are indeed implicit in the winding order. It probably works better with edge cases as well. |
OpenSCAD code. Result is a cube with a hollow center. But the center has an improper winding order. Good luck ;-) |
The center hole cannot be seen, so it's not problem. |
Referenced the wrong commit, this shouldn't be closed yet. |
MeshTools plugin has a fairly robust option to fix normals. |
Some models show wrong overhangs.
Perhaps the normals as described in the STL file are incorrect.
It would then be nice to recalculate the normals so that the right pieces are colored red.
The text was updated successfully, but these errors were encountered: