How to detect reversed faces (flipped normals)? - three.js

I need to load several STL files in a scene, some of which have reversed/flipped faces. This can be easily fixed (visually) using a double-sided material, but what I try is to visualize the wrong faces, switching the material index from blue to red.
If I understand, a mirrored/flipped/reversed face is being drawn clockwise instead of counter-clockwise. But are we talking about the three vectors that form the face? If so, the winding order is the order set at face.a, face.b and face.c? Or should I have to compare the face index value to know the order the face is drawn?
I set up a JSFiddle to ilustrate the problem: this STL model has 10 faces, and 3 of them are reversed or flipped. Using a FaceNormalsHelper you can see that those 3 normal helpers point to the inside of the model, instead outside. I´ve tried 6 different ways to check this, some of them are extracted from the code at computeFaceNormals(), with no luck. I´ve also examined the FaceNormalsHelper to see how it works, but it simply draws a line from the face centroid in the normals direction, but it never gets to calculate if it´s pointing inside or outside.
(Note: in order to change from one method to another, you must change the variable at the start of the script. Method 1 manually overrides these three faces material index, just to visualize the wrong ones (as a validation of all the other methods). No other one gets the good results.. But method 2 and 3 are really really close to it, although somehow two other faces are detected as flipped. I wonder if the face angle has something to do with this)
EDIT: The method suggested by #manthrax works perfectly, comparing edges of each face with all the other ones. If the edge is drawn the same way (example: face 1 edge a-b matches face 2 edge a-b, instead of b-a), it´s flipped. Basically, if a face has two or more edges marked as flipped, we can say the whole face is flipped. Check the JSFiddle to see it working.
function paintFlippedFaces(faceCheck){
for(var x=0; x<Object.keys(faceCheck).length; x++){
var flipCounter = 0;
if(faceCheck[x]['a-b']) flipCounter++;
if(faceCheck[x]['b-c']) flipCounter++;
if(faceCheck[x]['c-a']) flipCounter++;
console.log("face " + x + " has " +flipCounter+ " flipped edges" );
if(flipCounter >= 2){
geometry.faces[x].materialIndex = 1;
//geometry.faces.elementsNeedUpdate = true;
}
}
}

First off, "flipped" faces are totally subjective. You need to decide on some parameters.
For a convex object, there is a non-subjective definition.. for instance that the face normal, dotted with one of the face vertices, is > 0.
For non-convex objects you can make some guesses based on the winding order of the vertices, and whether any 2 edges contains the same ordering, implying that you have 1 front facing and 1 back facing triangle sharing an edge. (Which of those triangles is flipped, isn't necessarily identifiable in the non-convex case though.)
First, you'll have to .mergeVertices on your geometry, so that vertices are shared across faces... I think stl defines unique vertices for every triangle, so there's no concept of an "edge" that is shared by two faces.
Then you can loop through each face.. and basically any 2 edges that share the same 2 vertices, should have opposition ordering, or that faces are facing opposite each other..
So if 2 faces have an edge like 3,2 and 2,3 then they are both facing the same direction.. and the faces are consistent.
If two different faces both have an edge that are 3,2 and 3,2, then they are facing opposite directions, and you could flag both faces as possibly being flipped. The faces that get flagged the most times are the ones that are probably actually flipped.
Those are the best guess tests I can think of to determine inside/outside, but it's a tricky problem.
Blender has a couple "recalculate normals" methods for recomputing "inside"/"outside" that I think operate on a similar principle.. so you could also look at those.

Related

The shortest path between two points on a cuboid on its surface

I can't find a universal solution to "The Spider and the Fly Problem" (the shortest path between two points on a cuboid on its surface). Everybody solves a one specific case but what when two points can be anywhere?
My idea was to create an algorithm that considers various nets of a cuboid, calculates shortest paths on 2D and then returns the minimum but I have no idea for the algorithm to generate these grids (I guess hardcoding all combinations is not the best way).
Simplistic approach (only works where the points are on the same or adjacent faces)
Flatten the cube structure to 2d as follows...
Start with a face containing one of the two points. If this also contains the other point, you can stop there and the solution is trivial.
There are only 4 neighbouring faces. If any of them contain the other point, you can place that face adjoining the first, and plot the straight line.
Otherwise, then the points are on opposing faces. You need to try placing the final face adjoining each of the 4 neighbouring faces, and choose the shortest of the 4 alternatives. This will not always give the best solution, but it's not far off, and is cheap.
Generic approach
Jim Propp's surface distance conjecture is that For a centrally symmetric convex compact body, the greatest surface distance between two points is achieved only for pairs which are opposites through the centre. My conjecture based on that would be that the shortest distance is approximately where the plane made by the two points and the centre of the body meets the surface. So you simply need to find where that plane intersects the faces using 3d geometry, and use the faces that are crossed by the shorter of the two alternatives when looking at possible routes. If the plane runs along an edge of the cube (e.g. if the points are on opposite faces and are both between the centre of the face and the corner of the face, and those corners are linked by an edge) then routes through both faces should be considered, although I speculate they will be equivalent lengths.
This solution is more generic, and also satisfies scenarios where the points are on the same face, connected faces and opposite faces.
The only problem with this approach arises where the line between the two points passes through the centre of the body, which by definition means that the two points are exactly opposite each other, because that means the 3 points are in a straight line, so there isn't a plane...
I think this is a good question, for which the answer is not at all obvious. In the smooth realm, it is an extraordinarily difficult problem. Geodesics (shortest paths) on a sphere (which is a smooth analog of a cube) are easy to find. Geodesics on a biaxial ellipsoid (an ellipsoid of revolution; one cross section is a circle) are much harder to find. Finding geodesics on a triaxial ellipsoid (a smooth analog of a general cuboid) was a challenging unsolved problem in the first half of the 19th century. See the Wikipedia page.
On the other hand, geodesics on cuboid are made from straight line segments so are much simpler. But some of the difficulty of the problem remains.
You may be able to find some literature on the subject if you search for the term "net". A polyhedron cut along some edges so that it can be flattened is often called a "net". I was able to quickly find a site that claims (without proof) that there are just 11 different nets for a cub(oid). But I agree with you that hard coding all the variations is not the best way.
It's not even obvious to me that the approach using nets will work for all polyhedra. I think I see an argument that will work for cuboids, but for general polyhedra, even convex polyhedra, it is not known whether they must have even one net. See the Wikipedia page. I think a satisfying solution to the problem on cuboids should work more generally on polyhedra, and the net idea seems to be insufficiently general, in my view.
What I'm thinking might work is a dynamic programming solution, where you look at the different edges your path can pass through between the initial and final points. There is a hierarchy of edges (those on the starting face; those containing a vertex on the starting face; those on the faces adjacent to the starting face; etc.). For each point on each of those edges you can find the minimum distance to the start point, culminating in the minimum distance from the end point to the start point.
Another way to think about this is to use something akin to the reflection principle, except instead of reflections, we use rotations in space which rotate the polyhedron about one of its edges so that the other face adjacent to the edge becomes coplanar with the starting face. Then we don't have to worry about whether we have a good net or not. You just pick a sequence of edges so that the final point is eventually rotated onto the plane of the initial face. The sequence of edges is finite because any loop is not part of a minimal path. I'll think about how I might be able to communicate this idea better.
I solved the problem for cubes and cuboids by discretizing the cube edges, generating a big graph and solving graph shortest path problem. You can specify start point (sx, sy, 0), and algorithm will determine all shortest path to target points on top face (z = 1), here for 19 * 19 target points. Cube edges are divided into 100 parts. Graph with these settings has n=1558 vertices and m=464000(!) edges, inner loop of floyd_warshall_path() for updating shortest path distances is executed n³ = 3,781,833,112 times (takes less than 1 minute on Raspberry Pi400). Orange shortest paths flow through 3 cuboid faces, blue ones through 4. Algorithm generates OpenSCAD file as output. Details in this posting, all code in GitHub repo.
P.S:
I made experiments with 1 x 1 x 3 cuboid and was able to find examples where shortest path between two points needs to pass 5 faces. Code is submitted to GitHub repo, and details are in this forum posting.
Orange shortest paths are passing 3 faces, blue are passing 4 faces, and the new yellow shortest paths pass 5 faces! With "mirror" at bottom, allowing to see the bottom face with start point as well. This time cuboid edges are divided into 150 parts (149 inner vertices), and there are 49 * 49 top face target points for single start point on bottom face:
I implemented cuboid shortest paths completely different this time, no graph, and geometric distance calculations in 28 possible foldings of cuboid into plane, details in this new forum thread:
Efficient cuboid surface shortest path problem application
The much increased efficiency with all the sliders allows to change x/y coordinate of bottom face point, number of divisions in X/Y direction and which folding to display, with instantaneous display after any change. This allows to play with a cuboid and "see" how the shortest paths change (on top face as well as on side and bottom faces).
Scale to 50% size, 0.5fps animation shows the 6 foldings containing any shortest path. The animation corresponds to clockwise traversal of OpenSCAD 3D top face shown on the right.
With added top and bottom face view.
but for anyone still interested, this question was solved on stackxechange by "Intelligenti pauca" (with some nice diagrams): here is the original link
https://math.stackexchange.com/questions/3023721/finding-the-shortest-path-between-two-points-on-the-surface-of-a-cube
The "Simplistic approach" from "Richardissimo" was on the right track, you just need to check a few more cases.
Intelligenti pauca:
If the two points belong to adjacent faces, you have to check three
different possible unfoldings to find the shortest path. In diagram
below I represented the first point (red) and the second point (black)
in three possible relative positions: middle position occurs when the
path goes through the common edge, in the other cases the path
traverses one of the faces adjacent to both faces. The other possible
positions are clearly longer than these.
image1
If the two points belong to opposite faces, then 12 different possible
positions have to be checked: see diagram below.
image2
After mapping the points like this you can calculate the distances like normal on a plane an have min(possible distances) as your shortest path-length.

"face-based" vs "vertex-based" attributes in fragment shader

I'm writing a rather complex webgl application in three.js and in order to have more control on my mesh materials I'm defining them through shaders.
However, I'm facing a serious problem for which I could not find any truly satisfying answer. Let's assume the following strong pre-requisites:
my geometry is indexed, i.e. the vertices are NOT duplicated among faces and I don't want to change this
the geometry is stored in a THREE.BufferGeometry object, again I don't want to switch to THREE.Geometry
I don't want to duplicate faces and/or create new geometries
I don't want any two-ways rendering that would drop my framerate
Given the above, let's say I click on a triangle (i.e., shoot a ray and get the closest face intersecting the ray) of my geometry and I want such triangle to be highlighted with a different color.
I'm already performing this in a quite efficient way by assigning a custom vertex attribute, say 1.0, to each vertex belonging to a face to be highlighted.
In the vertex shader I define a varying with such vertex attribute and within the fragment shader I just execute the following (pseudocode):
vec4 frag_color=mix(default_color,highlight_color,(vert_attribute>1-eps));
where eps is a small value (say 1.0e-4).
The idea is that each fragment interpolates its corresponding vertex attributes, say Vatt_1, Vatt_2 and Vatt_3, and if all the three attributes get the value 1.0 thus their interpolation is still nearly 1.0 (not precisely because of some roundoff error, that's why I use a small tolerance eps) and the test is true.
If the test is true I have frag_color=highlight_color.
On the other hand, if at least one Vatt_i (i=1,2,3) is not 1.0 but the default 0.0, the interpolation at the current fragment is <1-eps and the test is false (giving frag_color=default_color).
This seems to work perfectly, but now I have the following problem that looks truly challenging (given the constraints 1 and 2 above):
I don't have any simple way in the fragment shader to know whether or not the current fragment belongs to a specific face (or stays within three specific vertices, which is the same). So, if I select two triangles T1 and T2, and by chance a third triangle T3 has one (or two) vertices shared with T1 and two (or one) vertices shared with T2 I get that T3 gets highlighted too because its three vertices get the attribute 1.0.
Of course, seen from a human perspective this shouldn't happen because the three "highlighted" vertices of T3 should "logically" refer to two different highlighted faces but for obvious reasons the fragment shader highlights also T3.
This is a quite general problem I guess, I read a lot of forums without finding any satisfying possible solution. I understand that "this is how it works" and that the fragment shader does not have any knowledge of the background triangle nor its vertices, but here I'm looking for some clever idea or trick.
Does anybody have any suggestion to face this issue? Sorry for bothering but just to prevent some possible arguments: I consider the four points 1-4 above as strong requirements because otherwise I'd have other problems related to the overall performance and I don't want to pay this price.
Thanks in advance
You can know if a point is inside a triangle using barycentric coordinates. This can be done at vertex or fragment shader level depending on your needs.
Just get the coordinates of the vertices of the triangle that you want to test and convert the coordinates of the current vertex or fragment to barycentric coordinates. After that a simple test of the value of barycentric coordinates will tell you if the point is inside the triangle or not.

UV-mapping a BufferGeometrys indices in Three.js

I'm having trouble UV mapping each side of a cube. The cube was made as a BufferGeometry where each side is a rotated copy of one side (sort of a working template) and rotated accordingly by applying a quarternion. UVs are copied as well. I'll skip any vertex coordinate I've seen before and rely on indices.
This leaves me with a total of 8 vertices and 12 faces. But I think I'm running short on vertices when I have to set all of my UVs. As obvious on the screenshot I've "correctly" mapped each side of the cube. But the top and bottom is lacking. I don't know how to set the vertex UV top and bottom faces.
Can I in some way apply several UVs on the same vertex depending on which face it is used in or have I completely lost the plot?
I could solve the problem by applying 6 PlaneBufferGeometry but that would leave me with 4*6=24 vertices. That is a whole lot more than 8.
I haven't been able to figure this one out. Either I've complete misunderstood how it works or what I'm trying to accomplish is impossible given my constraints.
With BufferGeometry, vertices can only be reused if all the attributes for that vertex match. Since each corner of the cube has 3 perpendicular normals, there must be 3 copies of that vertex.
If you have uvs, it is the same issue -- vertices must be duplicated if the uvs are different.
Study BoxBufferGeometry, which is implemented as "indexed-BufferGeometry".
three.js r.90

Detect hole in geometry

I am working with a serialization pipeline. I am taking a model and exporting it. I do not wish to export any model with a hole in a face. How would I detect a hole and report a error?
I have access to all vertexes, edges, faces etc.
Here is a picture of what I mean.
As you can see there is a hole in the face. I am fairly new to geometry so please try to explain in layman terms.
If a 3D object is "simple", meaning that it doesn't have holes, it satisfies Euler's Formula for Polyhedra, V - E + F = 2 where V is the number of vertices in the figure, E is the number of edges, and F is the number of faces. If you can easily obtain those three numbers, you can calculate the formula V - E + F. If the result is not 2, the object has a hole (or some other pathology like a pinch). In fact, you can tell how many holes the object has by V - E + F: if the number is 0, it has one hole; if the number is -2, it has two holes; etc.
Calculating V, E, and F can be a little tricky because vertices are generally shared by two or more edges, and edges are generally shared by two faces. You don't want to overcount; if three edges meet in a single vertex, you only want to count the vertex once, not three times.
Not only that, but it's easy to make a mistake counting when the shapes have holes (which is exactly the case you're interested in). The easiest way to avoid making a mistake is to break the figure up into convex parts with e.g., triangulation.
The formula doesn't tell you which face has the hole, but if you know that the figure has a hole you can apply Euler's formula to each face individually, again with triangulation. In that case, faces without holes will have V - E + F = 1 where V,E,F are now restricted to the face in question. (the discrepancy with the previous formula is resolved if you count the region outside the face as another (infinite) face). Faces with holes will have V - E + F < 1.
For example, a triangle on the plane has V=3, E=3, and F=1 (the "face" of the triangle represented by its interior) giving V-E+F=1. On the other hand, a triangle with a similarly shaped triangular hole inside, in which corresponding vertices of inner and outer triangles are connected, will have V=6, E=9, and F=3 for V-E+F=0. I have broken the figure into three convex quadrilaterals in this case.
Most books on computer graphics have a discussion of this topic.
If I understand correctly, you want to detect polygons with holes. Now how polygons with holes are represented can vary with each software (some store separate internal contour lists). However, a common representation in 3D packages (including formats like OBJ) use a flat face vertices representation which tends to look like this:
... where 2,6 and 1,7 would be the same vertex index stored twice in the same polygon (the numbers in the picture indicate face point indices). Note that this edge from 1,7 to 2,6 could be hidden in some software, but it's there even if it's not visible if the software stores polygon vertices in a flat list of indices/pointers.
So a quick way to tell if a polygon has a hole with such representations given only face data (ex: from an OBJ file) is to see if it has duplicate entries for the vertex indices. If the same vertex index is repeated more than one time in a polygon, then it has a hole.
Now there is a case where you can find duplicated vertices for an empty inner contour, like so:
... where 2,4 are welded (same vertex). If you want to distinguish these cases, you can detect them when the edge connecting exterior contour to interior contour only has one vertex duplicated instead of two. In that case, the interior contour is empty and this polygon is just a funky one (perhaps created through a CSG/plane slicing operation).
If you want a really robust solution, it's worth writing a routine that "unflattens" these flat contour lists into multiple interior/exterior groups by splitting the list apart where the duplicate edges connecting one contour to another are found. If the interior groups have fewer than 3 vertices, then they're probably just funky polygons without a visually noticeable hole. If they have 3 or more, then they meet the criteria required to show a hole which you can see visually. In cases where the interior contours don't form a full-fledged hole, you can just toss the interior contour and keep the exterior contour (in which case it's like just keeping the 3-point triangle exterior in the above pic while tossing out those redundant vertices, kind of cleaning up the geometry in the process and giving you the triangle formed from {1, 2/4, 5}).
A simple solution you can apply if you don't mind exporting unwelded geometry as long as it isn't funky (no holes or interior contours) is to simply clone (make unique) vertices that are duplicates in a polygon, basically unwelding it, like so:
That's a little easier than a full-blown tessellation kind of solution, and it still ends up giving you polygons without any holes or separate interiors. I visually moved 2 and 4 apart for the sake of demonstration to emphasize that they're now separate vertices, but you don't have to do that (they can be coincident).
This kind of unwelding technique is also useful if you have a tessellator that doesn't support holes. You can apply this technique to unweld the polygon, tessellate it, then weld/merge back coincident vertices to give you the final result.

Algorithm for labeling edges of a triangular mesh

Introduction
As part of a larger program (related to rendering of volumetric graphics), I have a small but tricky subproblem where an arbitrary (but finite) triangular 2D mesh needs to be labeled in a specific way. Already a while ago I wrote a solution (see below) which was good enough for the test meshes I had at the time, even though I realized that the approach will probably not work very well for every possible mesh that one could think of. Now I have finally encountered a mesh for which the present solution does not perform that well at all -- and it looks like I should come up with a totally different kind of an approach. Unfortunately, it seems that I am not really able to reset my lines of thinking, which is why I thought I'd ask here.
The problem
Consider the picture below. (The colors are not part of the problem; I just added them to improve (?) the visualization. Also the varying edge width is a totally irrelevant artifact.)
For every triangle (e.g., the orange ABC and the green ABD), each of the three edges needs to be given one of two labels, say "0" or "1". There are just two requirements:
Not all the edges of a triangle can have the same label. In other words, for every triangle there must be two "0"s and one "1", or two "1"s and one "0".
If an edge is shared by two triangles, it must have the same label for both. In other words, if the edge AB in the picture is labeled "0" for the triangle ABC, it must be labeled "0" for ABD, too.
The mesh is a genuine 2D one, and it is finite: i.e., it does not wrap, and it has a well-defined outer border. Obviously, on the border it is quite easy to satisfy the requirements -- but it gets more difficult inside.
Intuitively, it looks like at least one solution should always exist, even though I cannot prove it. (Usually there are several -- any one of them is enough.)
Current solution
My current solution is a really brute-force one (provided here just for completeness -- feel free to skip this section):
Maintain four sets of triangles -- one for each possible count (0..3) of edges remaining to be labeled. In the beginning, every triangle is in the set where three edges remain to be labeled.
For as long as there are triangles with non-labeled edges:Find the smallest non-zero number of unallocated edges for which there are still triangles left. In other words: at any given time, we try to minimize the number of triangles for which the labeling has been partially completed. The number of edges remaining will be anything between 1 and 3. Then, just pick one such triangle with this specific number of edges remaining to be allocated. For this triangle, do the following:
See if the labeling of any remaining edge is already imposed by the labeling of some other triangle. If so, assign the labels as implied by requirement #2 above.
If this results in a dead end (i.e., requirement #1 can no more be satisfied for the present triangle), then start over the whole process from the very beginning.
Allocate any remaining edges as follows:
If no edges have been labeled so far, assign the first one randomly.
When one edge already allocated, assign the second one so that it will have the opposite label.
When two edges allocated: if they have the same label, assign the third one to have the opposite label (obviously); if the two have different labels, assign the third one randomly.
Update the sets of triangles for the different counts of unallocated edges.
If we ever get here, then we have a solution -- hooray!
Usually this approach finds a solution within just a couple of iterations, but recently I encountered a mesh for which the algorithm tends to terminate only after one or two thousands of retries... Which obviously suggests that there may be meshes for which it never terminates.
Now, I would love to have a deterministic algorithm that is guaranteed to always find a solution. Computational complexity is not that big an issue, because the meshes are not very large and the labeling basically only has to be done when a new mesh is loaded, which does not happen all the time -- so an algorithm with (for example) exponential complexity ought to be fine, as long as it works. (But of course: the more efficient, the better.)
Thank you for reading this far. Now, any help would be greatly appreciated!
Edit: Results based on suggested solutions
Unfortunately, I cannot get the approach suggested by Dialecticus to work. Maybe I did not get it right... Anyway, consider the following mesh, with the start point indicated by a green dot:
Let's zoom in a little bit...
Now, let's start the algorithm. After the first step, the labeling looks like this (red = "starred paths", blue = "ringed paths"):
So far so good. After the second step:
And the third:
... fourth:
But now we have a problem! Let's do one more round - but please pay attention on the triangle plotted in magenta:
According to my current implementation, all the edges of the magenta triangle are on a ring path, so they should be blue -- which effectively makes this a counterexample. Now maybe I got it wrong somehow... But in any case the two edges that are nearest to the start node obviously cannot be red; and if the third one is labeled red, then it seems that the solution does not really fit the idea anymore.
Btw, here is the data used. Each row represents one edge, and the columns are to be interpreted as follows:
Index of first node
Index of second node
x coordinate of first node
y coordinate of first node
x coordinate of second node
y coordinate of second node
The start node is the one having index 1.
I guess that next I should try the method suggested by Rafał Dowgird... But perhaps I ought to do something completely different for a while :)
If you order the triangles so that for every triangle at most 2 of its neighbors precede it in the order, then you are set: just color them in this order. The condition guarantees that for each triangle being colored you will always have at least one uncolored edge whose color you can choose so that the condition is satisfied.
Such an order exists and can be constructed the following way:
Sort all of the vertices left-to-right, breaking ties by top-to-bottom order.
Sort the triangles by their last vertex in this order.
When several triangles share the same last vertex, break ties by sorting them clockwise.
Given any node in the mesh the mesh can be viewed as set of concentric rings around this node (like spider's web). Give all edges that are not in the ring (starred paths) a value of 0, and give all edges that are in the ring (ringed paths) a value of 1. I can't prove it, but I'm certain you will get the correct labeling. Every triangle will have exactly one edge that is part of some ring.

Resources