Optimising a scene with a lot of mesh

Hello, I’m currently working on a project where I need to have lots and lots of mesh on stage at some point. But a problem arises, the fps drops with this number of mesh … I find myself with 10 fps for 12k instance posed on my scene, but I would like to be able to pose more and have at least 30fps for it is still a minimum fluid to watch …
I’ve already optimised my glb with this link:

which has already made me gain a few fps.
to avoid having to load this glb at each pose I created instances of it which also made me gain some fps but after I block… I bo tried many things, nothing made I remain blocked at 15 fps…
Would you have any tips or advice that would allow me to achieve a drinkable number of fps?
thank you.

Hi @marius_margueray
Biggest gain to expect are indeed instancing and grouping meshes.
Also, check this link with many tips that can help:

https://doc.babylonjs.com/features/featuresDeepDive/scene/optimize_your_scene

How many faces/vertices per mesh instance ?

1 Like

Hello, thank you for the quick response to get me started.
It depends on the mesh used but we’ll say that it varies between 6 and 12 faces if I’m not being silly.
I’ve already looked at this doc but a lot of things that can be deactivated are useful for the rest of the program (apart from the posed instance we’re talking about) so it creates more problems than solutions… I’ve still taken a few things but in general it’s buggy.
I’ve just come across this page though, could it be more optimised than a classic instance?
https://doc.babylonjs.com/features/featuresDeepDive/mesh/copies/thinInstances

yes, thin instances are more performant. 6 to 12 faces is not a lot. Try merging meshes. 10K instances of 12 faces per instance is not a lot to render in term of geometry complexity.

1 Like

Is your scene anything like this: Babylon.js Playground

See if you can play around with mesh.alwaysSelectAsActiveMesh and scene.freezeActiveMeshes. While playing around, see the inspector performance tab

what did you mean by ‘merging meshes’ cedric?

joe, it looks like a ground where you can put instances with a ‘brush’ so once the user has finished ‘painting’ we can say that yes it looks like that. i looked a little on the freeze, i think it’s cool but is there a similar method that allows you to freeze only the mesh you want to freeze? it would be more appropriate for what i’m looking for. because after testing i double my fps so it’s more than interesting.
here are 2 images showing with and without freeze:


https://doc.babylonjs.com/features/featuresDeepDive/mesh/mergeMeshes

but I think using thin instances is more suited if you want to add and remove instances.

ha ok I didn’t understand… yes indeed it’s not the most adapted to what I want to do but I’ll keep it in a corner of my head you never know :thinking_face:

Is there still the drawback that removing thinInstances from the middle of the list still a little bit of a workaround? (copy last thinInstance matrix to the “deleted” thinInstance then set thinInstanceCount–). If you don’t care which thinInstance you’re deleting, then just thinInstanceCount-- will work?

bjr I’ve been studying the subject a bit and at the same time I’ve discovered the ‘Cloning With the Solid Particle System’, which I think have a bit of the same properties, don’t you?
but otherwise I have a few questions about thin instances:
is there a way of ‘dissociating’ them so that when I click on them I only see the bounding box of the one I clicked on?
How can I use coordinates (x, y, z) to obtain matrixes that allow me to place these instances? because I haven’t found any other way of placing them other than with matrixes…

You can only use matrices. but making a matrix from a position is easy. It’s an identity matrix with components 12,13 and 14 set to the position x,y,z.

EDIT: some more infos here : opengl - What's the purpose of magic 4 of last row in matrix 4x4 for 3D graphics? - Stack Overflow

Do setTranslation() and setTranslationFromFloats() also set translation without affecting rotation or scale? (Doc says “inserts…”)

On Matrix objects, yes. Thin instances use float array.

2 Likes

Depending on your use case, octree culling may also be useful: Babylon.js docs

1 Like

Good morning,
I’ve just looked at it, it’s not bad but for me it doesn’t change much…

I’ve thought about it a bit and I know that you can freeze all the meshes in a scene. But can you freeze only part of the mesh in the scene, because I have quite a few meshes that are dynamic depending on the modes selected, which poses a problem if I freeze…

and to return to this message, i’ve pushed the use which can indeed bring a significant gain but it doesn’t totally answer my request because i can’t do everything i can do with a classic instance. but the biggest problem is that once everything is added it’s just one mesh… and i’d like each mesh to have an independent bounding box…

Then keep track of it independently? I use Mesh.MergeMeshes for one large “level mesh”. I keep original bounding boxes in a data structure and can interact with original meshes via Havok.

Hello!
do you have a small example because I didn’t fully understand how you differentiate between them…
Thank you in advance!

Good morning,
I’m coming back here to put an end to the ticket. I’ve found a few things that have worked for me.
There’s still the ‘scene.freezeActiveMeshes()’ that I need to adapt for me, but it’s by far the best way to optimise a scene with a lot of mesh (or else I’ve missed a trick).

I’m still waiting, if you see the message, for a small example even though I’ve looked a bit more and have a little idea @Joe_Kerr.

Thank you for taking the time to help me.
Sincerely

1 Like

Yeah, no pressure :smiley: (just kiddin)


Not sure what’s unclear. So first of all maybe this one can help a bit: PhysicsShape.getBoundingBox() returns empty object - #6 by Cedric

Then returning to the general idea: There is a game level. A bunch of level geometry is loaded consisting of individual meshes. These meshes are all merged into one big level mesh (1 draw call). Each mesh has a bounding box you can get via mesh.getBoundingInfo().boundingBox. Before I merge the mesh (into the big “merged level mesh”) and dispose it, I clone the bounding box to retain the bounding box.

For interactivity I use Havok. Again, before merging the mesh, I create a physics shape from the mesh and use a TransformNode as the PhysicsBody parameter. This TransformNode acts as id to the original mesh (or rather my data structure that keeps all relevant infos about it [like bounding box]). N.B. Havok raycasts will return PhysicsBody.transformNode.

Obviously once all meshes are merged, they are gone. But I keep the vertex ranges of the now disposed former meshes within the big merged mesh. So I can delete “meshes” in the merged mesh. This could be expanded to allow any kind of transformation if you re-load the former mesh: a) hide vertex range in merged mesh, b) transform re-loaded mesh c) sync vertex range d) show vertex range e) hide/delete re-loaded mesh (sth like that)


Anyway, this is how it works for me. Not sure if you can adapt it to your case.