How to get position of procedural foliage?

Good day everyone,

I am using the [Redwood Forest Biome][1] world under Unreal Engine 4.26 in relation to a research project combining computer vision and drones. I need to extract the positions (+ some other properties like girth) of the procedural generated trees of the world in order to compute ground truth distances of trees from the drone.

Here is what I have in my main world :

Where the generated foliage is identified as an InstancedFoliageActor class.

I have limited knowledge of UE4 but I understand that if such a query is possible, I would need to insert a c++ function inside a new or existing class which could reach the foliage instances.
I have collected some leads ([How to get locations of foliage instances?][4] and [Accessing Vertex Positions of static mesh][5]) but I’m not sure to understand how to make it work inside an UE4 project.

Taking [How to get locations of foliage instances?][4] for example, I have tried modifying foliage related classes but witnessed nothing in the output log. I feel like I’m passing by something obvious… What am I missing ?

Thanks !

PS: I just need to extract the foliage instances properties once, no matter how, if it can directly be done via the editor terminal I’ll take it !

Hi, I only extracted the foliage with blueprints, but should ofc also work in C++. All the foliage is stored inside the InstancedFoliageActor which you can access through GetActorOfClass. It is stored in the form of HISMCs, so you will have one HISMC per foliage mesh. To access the HISMCs you can use GetComponentsByClass (and input Hierarchical Instanced Static Mesh Component) on the InstancedFoliageActor. Through the HISMC you can then access the static mesh that is associated with that HISMC and the array of transforms (all the instances of it in the world).

With blueprints you can also mark an event/function CallInEditor then you can directly run it from the editor without running the game.

Ofc that way you will only get the transforms of the trees but not the actual distance. Depending on how accurate you need your ground truth distance to be you could then just take the distance from the drone to the location from the transform. Or you could use linetraces (using complex, so per poly, collision) from your drone to the trees (utilizing the location you get from the transform) and then compute the distance via the hit location of that linetrace. Might be easier than to try extract vertex positions.

2 Likes

Hi chrudimer, thank you for your answer.
I managed to extract the foliage instances names but for one it’s incomplete and it’s not what I’m aiming for :
342122-
Some are even directly accessible in my world outliner:
342123-
, but the real trees I’m looking for aren’t listed.

For the sake of clarity here are the meshes used for the trees I’m targetting whose classes actually bear the same name :

I can also already list their names via the Python API when using the AirSim plugin which emulates my drone :

Here is the simple blueprint I made to achieve this :

The actor class selected in GetActorOfClass is ‘Instanced Foliage Actor’ and the component class selected in GetComponentsByClass is ‘Hierarchical Instanced Static Mesh Component’.

Appart from the trigger event, is it what you had in mind ? Am I querying the right class and components ?

1 Like

Appart from the trigger event, is it
what you had in mind ? Am I querying
the right class and components ?

Yes that is what I meant. You can then access the static mesh for each HISMC and compare it with those you’ve shown in your image trees-content.png to see whether that HISMC uses that static mesh. And you can access the transform (location, rotation, scale) for each of those instances (e. g. if the static mesh would be SM_RW_SQM1 then each instance would be a tree of with SM_RW_SQM1) via GetInstanceTransform. So with that you can get the transforms for all your trees.

Of course you can only access the instances that way (and since you access the HISMC via the InstancedFoliageActor only those that are in there, so what you place via Procedural Foliage Spawner / with the foliage paint tool). You can’t access static mesh actors that way. If you just drag and drop a static mesh into the world, then you will get a StaticMeshActor. So you cannot access anything of your world-outliner-river.png using that way.

If you want to access the transform for static mesh actors that use a specific static mesh, then you can use GetAllActorsOfClass with StaticMeshActor and then check what static mesh the static mesh component of the StaticMeshActor uses. The transform would then just be the actors transform.

You’ve been of fantastic help !
I’ve developped a V2 derived of your proposition which outputs me the transformations I want for tree instances only :

Here I’ve asked to print out both the position and component name of each tree instance :

It works fine which is great, but there are still grey areas I’d like to clarify.

  1. What is the difference between the values of the Break Transform node that’s connected to my print and the Break Transform node that’s isolated ? Because they output the same amount and type of data but with different transform values.
  2. Is there a more practical way to check the static mesh name against multiple values than through a billion ‘==’ nodes ?
1 Like

(1). A HISMC contains a certain number of instances (tree instances in your case) which you can get via the GetInstanceCount node. GetInstanceTransform needs to know which instance you want and you specify that via the InstanceIndex. So InstanceIndex 0 will be the first instance, 1 will be the second,… What is connected to your print is looping through all the instances of each HISMC and then you get the location value of the transform and print that. What is not connected will always output the transform of the 0 instance for each HISMC.

(2). You can create a new variable of type string and array and add all those names to this array. Then you can check whether that array contains the GetDisplayName (drag out from the array and type contains). And I guess I would rather check against the static mesh than against the name cause if you change the name of the asset (the static mesh of the trees) you will need to adjust the code but if you check against the static mesh then changing the name of the asset won’t make any difference.

Thanks to chrudimer’s feedback, I managed to come up with a blueprint solution that outputs every transformation of each instance of my tree components which are stored in the array of objects variable ‘Tree array’ :

Here is the terminal output :

To avoid printing out the full component’s class name, I split the string relatively to the space character and only retained the component’s name which comes last.

1 Like