R3F / three.js - Instanciate a combination of objects - three.js

In the following codesandbox example:
there are different geometries merged together thanks to drei library (2Boxes and 1 Sphere).
I would like to
have a lot of this new geometry with a good performances. I think the solution would be to instanciate the merged geometry but I do not know how to do it.
Still be able to control each part properties (for example, make a cube bigger than the other one in a special instance)
Could you please help me ?

A solution would be to:
Create an instanceMesh for each part of the geometry
Assemble each part by changing each geometry position
You can find this solution with 2 codeSandboxes:
one using the Drei librairy but which get laggy around 10k elements
one using instanceMesh from R3F which work pretty well with 100k elements.
I do not know if we can improve more the performance, but it seems to work pretty well like this.

Related

THREE JS Imported Model Size and Performance

I was hoping to display in my app as many as 3,000 instances of the same model at the same time - but it’s really slowing down my computer. It's just too much.
I know InstancedMesh is the way to go for something like this so I’ve been following THREE.js’s examples here: https://threejs.org/docs/#api/en/objects/InstancedMesh
The examples are fantastic, but they seem to use really small models which makes it really hard to get a good feel for what the model size-limits should be.
For example:
-The Spheres used here aren't imported custom 3D models, they're just instances of IcosahedronGeometry
-The Flower.glb model used in this example is tiny: it only has 218 Vertices on it.
-And the “Flying Monkeys” here come from a ".json" file so I can’t tell how many vertices that model has.
My model by comparison has 4,832 Vertices - which by the way, was listed in the "low-poly" category where I found it, so it's not really considered particularly big.
In terms of file-size, it's exactly 222kb.
I tried scaling it down in Blender and re-exporting it - still came out at 222kb.
Obviously I can take some “drastic measures”, like:
-Try to re-design my 3D model and make it smaller - but that would greatly reduce it’s beauty and the overall aesthetics of the project
-I can re-imagine or re-architect the project to display maybe 1,000 models at the same time instead of 3,000
etc.
But being that I’m new to THREE.js - and 3D modeling in general, I just wanted to first ask the community if there are any suggestions or tricks to try out first before making such radical changes.
-The model I'm importing is in the .glTF format - is that the best format to use or should I try something else?
-All the meshes in it come into the browser as instances of BufferGeometry which I believe is the lightest in terms of memory demands - is that correct?
Are there any other things I need to be aware of to optimize performance?
Some setting in Blender or other 3D modeling software that can reduce model-size?
Some general rules of thumb to follow when embarking on something like this?
Would really appreciate any and all help.
Thanks!
GLTF is fine to transmit geometry and materials — I might say the standard right now. If there's only geometry, I'd see OBJ or PLY formats.
The model size is blocking, but only for the initial load if we employ instancing on its geometry and material. This way we simply re-use the already generated geometry and its material.
At the GPU level, instancing means drawing a single mesh with a single material shader, many times. You can override certain inputs to the material for each instance, but it sort of has to be a single material.
— Don McCurdy
Our biggest worry here would be the triangles or faces rendered. Lower counts of this are more performant, and thus, fewer models at a time are. For this, you can use some degree of LOD to progressively increase and decrease your models' detail until you stop rendering them at a distance.
Some examples/resources to get you started:
LOD
Instancing Models
Modifying Instances

Is there a way to change mesh geometry and/or material dynamically without scaling?

I created an object and I want to change dynamically the geometry of that object. the only answer I could find so far was to implement scaling on that object, but it's not what I'm looking for, because it requires constant calculation and it's a bad solution for me. I will be happy to hear any tips and suggestions.
Using scaling is one of the fastest ways to change a geometry, as it only changes one of the parameters already used in the projection calculations. Other generic ways of modifying a geometry will be significantly slower, as every vertex needs to be updated and transferred to the GPU.

Hide/show parts of a BufferGeometry

I build a complex BufferGeometry from scratch and I am looking for a way to selectively hide or show sections of it - (I don't want to have to save the positions elsewhere so moving vertices around is not an option)
After reading the code a bit, I wondered if I could use BufferGeometry.groups except that I don't want/need a different material per group - maybe assigning a different material could work and I could make the opacity 0 for parts I don't want? However, here will be many thousands of groups though so I doubt that would be effective.
Started a JSFiddle with a boiled down example: http://jsfiddle.net/callum/x7y72k1e/
Is there a way to do it efficiently?
(As I'm typing this, I wonder if I just store the positions in a mirror attribute array and use that).

Three.js How to increase canvas-text texture quality

What parameters, modes, tricks, etc can be applied to get sharpness for texts ?
I'm going to draw a lot so I cant use 3d text.
I'm using canvas to write the text and some symbols. I'm creating somethinbg like label information.
Thanks
This is no simple matter since you'll run into memory issues with 100k "font textures". Since you want 100k text elements you'll have several difficulties to manage. I had a similar problem too once and tossed together a few techniques in order to make it work. Simply put you need some sort of LOD ("Level of Detail") to make that work. That setup might look like following:
A THREE.ParticleSystem built up with BufferGeometry where every position is one text-position
One "highres" TextureAtlas with 256 images on it which you allocate dynamically with those images that are around you (4096px x 4096px with 256x256px images)
At least one "lowres" TextureAtlas where you have 16x16px images. You prepare that one beforehand. Same size like previous, but there you have all preview images of your text and every image is 16x16px in size.
A kdtree data structure to use a nearestneighbour algorithm with to figure out which positions are near the camera (alike http://threejs.org/examples/#webgl_nearestneighbour)
The sub-imaging module to continually replace highres textures with directly on the GPU: https://github.com/mrdoob/three.js/pull/4661
An index for every position to tell it which position on the TextureAtlas it should use for display
You see where I'm going. Here's some docs on my experiences:
The Stackoverflow post: Display many thousand images in three.js
The blog where I (begun) to explain what I was doing: http://blogs.fhnw.ch/threejs/
This way it will take quite some time until you have satisfying results. The only way to make this simpler is to get rid of the 16x16px preview images. But I wouldn't recommend that... Or of course something depending on your setup. Maybe you have levels? towns? Or any other structure where it would make sense to only display a portion of these texts? That might be worth a though before tackling the big thing.
If you plan to really work on this and make this happen the way I described I can help you with some already existing code and further explanations. Just tell me where you're heading :)

ThreeJS: is it possible to simplify an object / reduce the number of vertexes?

I'm starting to learn ThreeJS. I have some very complex models to display.
These models come from Autocad files that my customer provides.
But sometimes the amount of details in the model is just way too much for the purpose of the website.
I would like to reduce the amount of vertexes in the model to simplify the display and enhance performance.
Is this possible from within ThreeJS? Or is there maybe an other solution for this?
There's a modifier called SimplifyModifier that works very well. You'll find it in the Three.js examples
https://threejs.org/examples/#webgl_modifier_simplifier
If you can import the model into Blender, you could try Decimate Modifier. In the latest version of Blender, it features three different methods with configurable "amount" parameters. Depending on your mesh topology, it might reduce the poly count drastically with virtually no visual changes, or it might completely break the model with even a slight reduction attempt. Other 3d packages should include a similar functionality, but I've never used those.
.
Another thing that came into mind: Sometimes when I've encountered a too high-poly Blender model, a good start has been checking if it has a Subdivision Modifier applied and removing that if so. While I do not know if there's something similar in Autocad, it might be worth investigating.
I updated SimplifyModifier function. it works with Textured models. Here is example:
https://rigmodels.com/3d_LOD.php?view=5OOOEWDBCBR630L4R438TGJCD
you can extract JS codes and use in your project.

Resources