How to procedurally select leaves of a tree?

   264   5   2
User Avatar
Member
52 posts
Joined: Sept. 2016
Offline
Hi everyone,

I have a tree model and I want to select its leaves for further applying materials, so I need to separate the leaves from the trunk/branches. The good news is that all leaves are the same shape, have the same point count. Any ideas how to select them?
Thanks.
Edited by Emil - Sept. 6, 2026 14:36:45

Attachments:
leaves.png (2.3 MB)

User Avatar
Member
424 posts
Joined: Aug. 2018
Online
How about:
Connectivity SOP to generate a per piece 'class'
Then a Measure SOP to get the leaf area per piece and selecting on the basis of that?
User Avatar
Member
9728 posts
Joined: July 2007
Offline
You can additionaly decide by other factors unique to your leaves and not branches

- Like if your leaves have open boundary but the branches are closed
- Or since all your leaves have exactly 5 polys and 10 boundary points so if none of the branches do you can use that also to distinguish them
- or in case they have uvs and leaves and branches are already in different udim or clearly separated section of UV tile
- or average normal length will be much closer to 1 for flat leaves than for round branches, should be enough difference to find a clear threshold value
...

Essentially find the qualities that you think are the most robust way to distinguish leaf from other geo and you can use that when you run over the connected pieces, ideally consider all the models you want to apply it to potentially come up with a test that works for all if possible
Edited by tamte - Sept. 6, 2026 17:18:21
Tomas Slancik
CG Supervisor
Framestore, NY
User Avatar
Member
52 posts
Joined: Sept. 2016
Offline
Mike_A
How about:
Connectivity SOP to generate a per piece 'class'
Then a Measure SOP to get the leaf area per piece and selecting on the basis of that?

Thanks Mike_A for your reply.

Yes my first attempt was using the Measure SOP to isolate those leaves based on the @area attribute, but along with the leaves, the tiny branches also got included into that threshold making that group unusable.
User Avatar
Member
52 posts
Joined: Sept. 2016
Offline
tamte
You can additionaly decide by other factors unique to your leaves and not branches

- Like if your leaves have open boundary but the branches are closed
- Or since all your leaves have exactly 5 polys and 10 boundary points so if none of the branches do you can use that also to distinguish them
- or in case they have uvs and leaves and branches are already in different udim or clearly separated section of UV tile
- or average normal length will be much closer to 1 for flat leaves than for round branches, should be enough difference to find a clear threshold value
...

Essentially find the qualities that you think are the most robust way to distinguish leaf from other geo and you can use that when you run over the connected pieces, ideally consider all the models you want to apply it to potentially come up with a test that works for all if possible

Thank you Tomas for your reply.

Yes, using the point/vertex count seems decent option, so since I know the vertex count on the leaves, I tried to delete based on that but the code does not seem to do anything:

if (primvertexcount(0, @primnum) == 20) {
removeprim(0, @primnum, 1);
}


I managed to select the leaves based on the UVs, just using Select > UV Connected Geometry, no coding needed. But I am curious as an alternative or if I had not the UVs, what was wrong with the code so it didn't do the trick?
Edited by Emil - yesterday 01:35:38
User Avatar
Member
26 posts
Joined: Aug. 2021
Offline
Hello. That code doesn't work because it finds the number of vertices for each primitive, and not for each piece. It will delete entire tree once it crosses threshold primvertexcount(0, @primnum) <= 3. However, there aren't any polygons in your mesh with 20 vertices. Condition will get evaluated as false and nothing will be deleted.

To fix this, code needs to be aware of the pieces and not just individual prims. I'd drop Connectivity with "Primitive" type to get i@class which we will then use in primitive wrangle. Then we count the number of prims that share the same class value. Leaves have the least number of polygons so they're the ones that get detected first.
int prim_count = findattribvalcount(0, "primitive", "class", i@class);
if(prim_count <= chi("thresh")){
    removeprim(0, @primnum, 1);
}

This method also works with SpeedTree's trees. You can optionally drop Fuse before Connectivity. Some trees from SpeedTree have these separated caps on small branches that kept getting flagged by this vex condition. Based on the image I don't think you will have that issue.

I hope it helps!
Italimpex Productions
CGI Studio specializing in directing and producing advertisements & films
  • Quick Links