The subdivision of a face follows a certain pattern. As Martynas Žiemys also correctly discovered, the points on the edges of the original faces have lower indices than the points in the center, because they are divided first.
Studying vertex indices when applying Subdivision Surface modifier it seems as if vertices with new increasing indices are added when subdividing. They seem to be first added to the existing edges and then they are 'connected' and vertices are added to intersections.
So that's true.
And lemon commented in his answer:
- vertices of edges are indexed first
- then inner vertices of faces are indexed in second (face per face)
- and center vertex is the middle of this last indexation
And that is also true.
But both proposed solutions unfortunately did not lead to the goal and could not solve the problem satisfactorily and in all cases.
For example, if you create the following mesh with Geometry Nodes before (and this is the case in my example) and the subdivision level is greater/equal $2$, then their approach does not work:
So I took another look at the issue, and created a combination of math and logic game...
Reliably select the inner points of subdivided faces
Selecting the points within the faces is a relatively simple game, as it turns out.
All you need to know is how many points ($Po$) and edges ($Eo$) the original mesh had before the subdivision.
And with each subdivision ($S$), additional points are created on the existing edges. This looks like this:
||Additional Points on Edges
This value is obtained with $2^S-1$.
Now, multiplying this value by the number of edges existing before the subdivision, and adding it to the number of points existing before the subdivision, we get the number of all points running along the original edges after the subdivision ($Pt$):
$Pt = (2^S - 1) * Eo + Po$.
Since these points always have the lowest index of the points added by the subdivision, any index higher than or equal to this value is a point in the inside of a subdivided face.
This reliably gives you a selection that includes only the points inside the faces:
(Inverse selection, points lying along original edges).
Find the middle point within this selection
If a face has 3, 5, 6 or more vertices, then this procedure is simple.
For a face that does not have four vertices, the center point is always the point whose number of adjacent points is equal to the number of vertices of the original face.
But it is even simpler, as I found out:
For a face that does not have four vertices, the point in the middle after a subdivision always has the lowest index of all points lying within the face!
(Subdivided pentagon with lowest index in the center)
Thus only one switch is needed to distinguish between faces with four vertices and all others.
For faces with four vertices, the middle point always has the middle value of the values of all points lying within a face.
(Index Range from $741$ to $749$, and the center has index $745$)
And to do this, you need to calculate how many points lie within a face.
Since this depends on the subdivision level, this is achieved by the following formula:
And so, for example, with a number of $9$ points, you would have selected the point with the index $4$ (Reminder: The index starts counting at $0$).
With the previously mentioned switch you can now toggle between the value $0$ (for faces with more than four vertices) and this average value (for faces with exactly four vertices).
In the last step we only have to compare the current index with these values.
And in this case we have to start counting again at $0$ for each face, so we politely ask the node
Accumulate Field to create a new counter for each face, so that the indices of all points that are inside a face and start in a new face will always start counting at $0$.
Since I capture the index of the faces in the domain Face before the subdivision with
Capture Attribute, these values remain in the points even after the subdivision. This is because the interpolation (from Face to Point) of these values only takes place at the points along the original edges, but not at the points created by the subdivision inside the original faces. Thus all points within the original faces always receive the same original value, which I use as a Group Index for
Accumulate Field. This way the counter can start counting again at $0$ for each original face.
(All points within a face use the original face index as Group input of
(Iterate through the indices of a face and capture the midpoint with index $4$)
So if one of the indices obtained in this way is equal to the value calculated before, then it is the midpoint of a subdivided face:
And in this example, with a subdivision level of $2$, the center index is $4$.
...Yay! The center point has been found!
And the node group ended up being simpler than initially thought:
And the coolest thing about this solution is:
- This node group can handle faces with any number of vertices.
- It can be used with all geometries, even if they were created in a "strange" way.
- The solution is extremely performant.