About InstancedMesh

I have a gltf model and it’s sub-objects all have their position in the world, but I now want to use the geometry of these sub-objects to create an InstancedMesh, since I want to manage the position and rotation of each object individually, I want the geometry Perform the following operations: “Scale”, “Normalize to origin”, “Unrotate”

1 Like

@mjurczyk Can you help me? please!

Doing chains like that by hand is unnecessarily complex and unreadable, can be as simple as:

  1. Load your GLTF.
  2. traverse the GLTF and collect all meshes within it:
const meshes = {};

gltf.scene.traverse((child) => {
  child.visible = false; // This will skip rendering of this GLTF entirely, which you want, as it will be replaced by instances

  if (child.isMesh) {
    meshes[child.uuid] = child.clone();
  }
});
  1. Create InstancedMesh for each collected mesh from meshes.
  2. Add copies of your GLTF to the scene - position, rotate, and scale them however you wish.
  3. Before rendering next frame, whenever any mesh within any copy of the GLTF was updated, sync it’s world position, location, and scale with a corresponding instance using .matrixWorld or just getWorldPosition / getWorldQuaternion / getWorldScale. That way you also won’t have to worry about nested matrix transformations.
1 Like

So should I apply the scaling and displacement originally applied to the gltf model to the InstancedMesh?

    let trash = model.children[1] as Object3D;
    let trashMesh = trash.children[0] as Mesh<BufferGeometry, MeshStandardMaterial>;

    let geometry = trashMesh.geometry.clone() as BufferGeometry;
    let material = trashMesh.material.clone() as MeshStandardMaterial;

    let mesh = new InstancedMesh(geometry, material, 10);
    mesh.instanceMatrix.setUsage(DynamicDrawUsage);
    mesh.scale.multiplyScalar(0.1);
    mesh.position.multiplyScalar(0.1);
    mesh.castShadow = true;
    mesh.position.set(0, 2, 0);
    mesh.add(new AxesHelper(10));
    render.scene.attach(mesh);

The InstancedMesh I created like this, although I applied scaling and displacement, I found that the geometry was still in the original place and at the original size.


like this,Just like this, this model is still so big

I’m lost in InstancedMesh, please help me :sob:

Because I cloned more than 500 sub-objects in the gltf model in one scene, I thought of using InstancedMesh to reduce the rendering burden.

it’s going to cause a mess either way because with instances you loose grouping and relative positioning. instance is a glob. it is so hard to instance a model for that reason because models are constructed as a scene graph of nested parts. traversal picking and plucking out things is going to destroy the source data.

the only solution i know of is in react, just to see it, open your shell and type

npx gltfjsx yourmodel.glb --transform --instanceall

what you see there now in the *.jsx file is the instanced scene with all its natural grouping and nesting. the model can be re-used thousands of times with the same amount of draw calls. if it has 10 different parts, using it 100.000 times you still only have 10 draw calls. gltfjsx also figures out similar geometry, if you re-use a model in blender, say a wheel, it counts against a single instance. every part of it can now be scaled, moved, changed just like you alter any other object3d in the scene.

https://twitter.com/0xca0a/status/1552372534397501446

in vanilla you have to write something specific to your model and usecase.

I can no longer import react. I want to limit the size of my final package. Is there any way to split the sub-objects in my gltf model, cancel its geometry rotation, normalize the origin, and scale it?

Help me, I’m dying in InstancedMesh

Post a working example of what you CAN implement/have implemented, even if it is running slowly… and then perhaps someone here can show you how to fix it. This means a codepen, jsfiddle or similar.

What you are doing here is the equivalent of asking a mechanic to fix your car via email. It’s disrespectful to ask people to implement things for you, without putting in the minimum effort.

Please please actually read this post and follow the instructions, before starting another topic:
https://discourse.threejs.org/t/please-read-this-before-posting-a-question/24/2

Oh, I’m sorry, please forgive me for being rude… (It may also include my words, because I am using Google Translate, and the machine translation may not be clear and a little reckless)

That’s ok. Can you please read the post I linked, and then create a working example, including the gltf file that you need to get to work.

Okay, I’m doing it! please wait

1 Like

This is my example, but by rewriting this example I seem to have discovered where my performance bottleneck is. Sorry again for being rude and thank you so much for your help!

I see my problem is still there, can you help me look at it again?

In the Performance panel, set CPU to 4x Slowdown and Hardware Concurrency to 2

Changing CPU and concurrency doesn’t seem relevant to the topic you’re asking about.
You may need to read up on how InstancedMesh works. It lets you render many instances of a single geometry, quickly.

For each unique geometry in your gltf, you will need to make a corresponding InstancedMesh of a count equal or larger than the total number of instances of that geometry that you will ever need.
Create your trash pieces as you do now, but instead of adding them to the scene, add them to your own separate Scene.

Each frame, call yourScene.updateMatrixWorld(true) to update all the matrices.
Then for each trash object… get the InstancedMesh for its geometry, and set the instanceMatrix for that objects id, to the object.matrixWorld.

Here’s a wrapper class I made/use called InstanceGroup that tracks and updates bunch of meshes and instances:

https://friendly-voltaic-viola.glitch.me

1 Like