Forest with Colliders

I’m working on a nature scene that allows players to “plant” trees using a raycast system. I want each of these trees to have larger primitive colliders around them to prevent players getting too close to the trees. I found that having “check collisions” enabled on the thin trunks of the trees directly involved inconsistent collisions. Often times I would end up going through part of the tree and get stuck inside, hence why I want to create a larger collider around the trees. Maybe there’s an easier fix for this.

There may be hundreds of trees and I’d like to know the most performant way to approach this. As I understand I can’t use thin instances for this as these trees are dynamically placed. Currently, I’m using clones, but “regular” instances look to be better for performance.

Is it possible to create instances that include child meshes? The parent object would be a large box collider around the tree (not rendered), while the tree mesh would reside inside of it. The box would have “checkCollisions” enabled but I don’t believe I can create instances using this layout but I could be wrong. Would I need to create an instance of the tree mesh and box mesh separately then parent them?

I wonder if you could have a set of instances of the tree mesh and then just a separate bunch of instances of the collider box with the same position as your trees? Does that make sense?

I couldn’t easily find a way to make an instance with its child attached.

1 Like

Yeah, that’s what I was trying to say up above. Create instances of both the box and the tree. Are the instances based on using the same material, or separate meshes?

When I try to create an instance of a mesh that has multiple materials I can only create an instance of one part of that mesh (based on one material).

I’ll need to experiment with this, maybe even go through in Blender and combine textures to use one material for each tree.

As I understand I can’t use thin instances for this as these trees are dynamically placed.

Hi @jgonzosan This is not true. You can update the coordinates of thin instances as well. See this PG from babylon documentation: Babylon.js Playground

You can incrementally add more thin instances by using:

var idx = sphere.thinInstanceAdd(matrix);

where the matrix is the transformation matrix that applies position, scale, and rotation to your instance.

The example also use a different syntax for the 2nd instance:

    var idx2 = sphere.thinInstanceAddSelf();
    sphere.thinInstanceSetMatrixAt(idx2, matrix2);

It shows how you can create a 2nd instance idx2. And then apply transformation matrix to update its transformation (pos, scale, rot).

I have scenario to add watch tower, castle wall, etc dynamically. What I did is the instantiate instance 0 as a ‘template’, because it is shown at ‘mouse cursor’ location to help user see where this unit will be located. After confirmation, this template instance 0 is moved to somewhere like position.y = -500, and a new instance 1 is created and allocated at the confirmed mouse cursor location.

1 Like

When I try to create an instance of a mesh that has multiple materials I can only create an instance of one part of that mesh (based on one material).

I don’t know if a mesh can have multiple materials. Do you mean your model is made up of multiple meshes, and these meshes use different materials?

Right now I have a tree mesh that has a material for the trunk and one for the leaves. I can assign different materials to different parts of the mesh by assigning certain faces of that mesh to a material in Blender. Here is what I’m talking about:

When importing this and trying to reference the model it’ll appear in “pieces” based on the materials used. For example for that pine tree it’ll show up like this when I console log meshes:

name: "Pine_primitive0"
name: "Pine_primitive01"

If I combined everything into one material it wouldn’t be an issue, but it can be a tedious process.

I’ll have to experiment with thin instances to see if they’ll work for my use case. If I can dynamically create thin instances with unique position/scale/rotation then I’ll use that. As of right now I’m just cloning.

name: “Pine_primitive0”
name: “Pine_primitive01”

Yes this is what I thought. You can leave them as two separate meshes in your model file. Babylon has this BABYLON.Mesh.MergeMeshes utility to merge an array of meshes into one. And the materials for these 2 meshes would become a MultipleMaterial that has references to the 2 actual materials. See Merging Meshes | Babylon.js Documentation.

Now you should be able to create thin instance on the returned single mesh from the MergeMeshes utility function.

Note if you have different materials, your draw call would be 2 for two meshes instead of 1. This is only problem to rendering performance if you have too many different models in your scene. E.g. if you have 100 different trees (birch, aspen, pine, christmas tree, etc), each is made of 2 meshes. Then you end up with 200 draw calls instead of 100.

I’m trying to implement the merging of the meshes after importing but keep running into an error where it can’t read the length. I created a playground using a basic cube with two materials:

I’m not sure what the issue is. I grabbed just the meshes array and tried to cast it as a Mesh array so I don’t know if that’s causing the issue. I also used the same arguments as shown in one of the examples. The examples in the docs use meshes created in Babylon, not sure if it changes when importing a mesh(es). If I could merge these meshes with multiple materials and use that with thin instances it would save me a lot of time.

See this:

You included the root mesh as well. I applied a filter to the meshes array and only provides the 2 meshes into the MergeMeshes function.

1 Like

Thanks, I initially had “shift” in my code to just keep the other two elements in the array and it wouldn’t work. Then I tried it again in the playground and it worked. Something weird was going on or wasn’t being updated but it looks like it’s working. I swear programming makes you feel like you’re going crazy sometimes. Here is my updated playground that includes “createInstance” as well just to ensure it’s working:

Thanks for the help, this will definitely help my workflow and performance.Going to mark this as solved.

1 Like