Detecting flat mesh faces

I’m trying to pick a mesh facet which is on a flat face of an arbitrary mesh. Babylon.js Playground

I’m getting the vertex normals, grouping them by facet, picking a facet, and then confirming that the vertex normals for that facet are aligned. It works with the complex D6, but the D20 it always seems to pick a facet that is on the point. I am unsure how these vertex normals would be aligned as I would think they would be averaged to different values since they are in a rounded area. Is there something I am doing wrong or is this not a reliable way to detect flat faces? I could maybe try to check the adjacent facets, but I’m not sure how to do that. Any advice is appreciated.

I displayed the vertex normals and the facet normals and it is clear that I am doing something wrong.

I realized that I wasn’t taking into account the fact that indices repeat in the array, so I updated the PG The result is in the image. Clearly the vertices are not grouped correctly as these three are not on the same facet. I also think the normals look wrong as I would expect that the normals would diverge due to averaging. So I’m hopelessly lost trying to correctly read vertex data and correlate to a facet.

Have you checked our

1 Like

I have, but I didn’t see anything in there that helped. Is there something specific I should look at to understand how vertices correlate to facets. I was going off the information here - Create Custom Meshes From Scratch | Babylon.js Documentation, specifically

Indices forming a facet are placed together in triples, as in the above example with (0, 1, 2) and (3, 4, 5) . The indices data is also stored in an array of numbers with each triple being kept together.

So I am assuming that the facet order matches the indices order (in that the first group of 3 indexes are the vertices for the first facet and so on), is that not the case? But given that I am not even getting vertices grouped together right, I suspect I am not understanding how to read vertex data even if the assumption about facet to indices relationship is valid.

Blake’s reply to this post helped me figure out what I was doing wrong. Find coordinates of facet vertices - #3 by Blake. I’ll have my updated PG with the solution posted shortly.

I updated my PG ( and it is now correctly detecting facets of flat sides for the complex d6 model. However, this approach doesn’t work for the d20. The problem appears to be that a side of a d20 can be represented by a single tri. So the vertices of that tri would all be adjacent to an edge and therefore the normals would be averaged. Any ideas how I could handle this? The only thing I can think of is maybe to check surface areas. If a facet surface area is really small compared to the total surface area of the mesh, than it is likely an edge facet.

1 Like

There are a couple of features of FacetData that would be useful to you

facetNormal this returns the normal perpendicular to the facet not the normal of a facet vertex.

Alternatively you can of course calculate this yourself, as follows.

Facet f has indices, a, b, c. Using the vertex positions array you can calculate the vector positions A, B, C for indices a, b, c. Then you can calculate the vectors vecAB and vecAC of the edges AB and AC, then the cross product for vecAB, vecAC will give you the normal for facet f. You will find the logic and code to do this within the following

Thanks. Per my last post I’m getting the facet normals and the vertex normals and can compare them. The problem is that when the entire side of the die is a single facet, the vertex normals are averaged with the adjacent facets so they don’t match and a flat face is not detected. If I were to clone the mesh and create a flat shaded copy that would make the side vertex normals align with the facet normal, but it would’;t help because all of the edge facet normals would align with their respective facets, right? The only way I can think of to detect side facets when the entire side is a facet is that the area of the side will be much larger than the area of an edge facet. So If I iterate the areas, sorting by the largest and throwing away any facets whose area is less than say 10% of the smallest, I think I might end up with the 20 sides of the d20. Unless you can think of a better way.

Surface areas probably won’t work. For the D20, the sides all have area of .0050, but the long edge meshes have area of .0047 which is 94% of the side area. Maybe what I need is to determine if there are any really short facet edges. Compare the lengths of the edges of the facet and if any are less than say 10% of the other edges throw the facet out? I think I also need the area check to throw out any facets at the point.

My thinking must be different to yours.

My approach would be

Two facets are are adjacent if they have an edge in common.

For facet f with indices a, b, c in that order then edges can be formed from a, b and b, c and c, a. You can form edge names such as Math.min(a, b)+“_”+Math.max(a, b) which can be compared facet by facet.

You can then check if facets f and g, are adjacent, if they have the same facet normal (within epsilon) they belong to the same face.

This way you can find all faces.

I don’t understand how that helps differentiate edge facets from face facets. In the d20 model, the entire face is a single facet so there would be no two adjoining facets with the same normal.

Do not understand why that causes a problem.

Sorry, maybe I haven’t been clear about what I am ultimately trying to achieve. I need to identify the numbered faces of an arbitrary die mesh so I can pick a facet from one of these at random and apply a rotation to align the facet normal with the +y axis. My current approach is to confirm that a selected facet has vertex normals that are the same as the facet normal. It works great for the complex d6 which has multiple facets per numbered face. But it doesn’t work at all for detecting numbered faces on the d20.

I follow that. My method does not use vertex normals. Whether a face is made up of 1 or more facets does not matter. All faces are identified as well as their face normals.

I’m sorry, I must be missing something. I still don’t understand how your approach differentiates facets from the numbered sides from facets that are part of the edge or the point. If I wanted to display a facet normal only for each of the 20 numbered sides of the d20 die, could you explain how I can do that with your method? I get that I would know that the facet for the numbered side would have a different facet normal than it’s neighbor. But how do I know which facet is the numbered side?

Are you sur you want to work with the model normals here ? With digged holes and smooth edges you end up with a lot of normals not aligned with the dice face (and not each face of your dice have the same count of triangles)

I’m not sure about your use case but can’t you go with a list of normals for each dice size ?

[vec3.down, vec3(0.7, 0.4, 0.2), vec3(-0.7, 0.4, 0.2), vec3(0, 0.4, -0.8) // d4 (approximately)
[vec3.up, vec3.down, vec3.right, vec3.left, vec3.forw, vec3.back] // d6

And pick one at random from the list as the new “up” for your throw ?

I considered that approach, but didn’t want to constrain the models to have a specific initial orientation. I would be willing to stipulate that the model must have one of the faces up and then I could search for facet normals with the alignments I would expect, but determining the orientation about Y would be difficult. I’d essentially have to determine a normal direction for the adjacent face to the +y face and then sweep that in a circle (producing a cone) and try to find a normal that lies in that cone. Once I have 2 normals, finding the others is just a matter of looking for normals with known orientations based on the overall model orientation. It might ultimately be a better way to do it due to the wide variety of geometries in the models as you suggest.

If you really need to “detect” the normals for an arbitrary dice, one way to go could be to iterate throught all the model normals, then count how many times each normal is repeated*, and pick the 6 (or 20, or 4…) normals that appear the most : that could do the trick - and it’s quite easy to implement.

*perhaps with some tolerance about how two normals are equals, if your object it smoothed.

Yep. Except for the case of complex (smooth edged) d20, d8, and d4 where the numbered faces are a single facet. But maybe you are onto something. The normals for the faces would have angles between them that are much larger than the normals of the edges and the points. Also if I average all of the edge normals together the resulting normal would be half of the angle between adjacent numbered faces. But at that point, I think my idea of comparing the facet width and height and eliminating any facets with very high AR (along with any facets that are tiny in terms of area) would be easier.