Inspired by a GScatter (plugin for blender) in Three.js
Spread all types of objects/models into a geometry easily
npm i @jaimebboyjt/three-scatter
Three.js already comes with MeshSurfaceSampler you can think in three-scatter
as an "extension" of it. I said it in quotes because is not quite true, three-scatter
the approach is different and it comes with method to help scatter your Meshes.
Use three-scatter
if you:
- Would like to scatter complex models (3D models with animations, rigging, etc)
- Want to align your model to the surface base, easily
- Would like to tweak in real-time (or with panels) seeds, or any property of your 3D model to scatter
- Want to remove collisions, easily.
NOTE: if performance is your must, MeshSurfaceSampler is your go to, I provided a debug option to help you, but MeshSurfaceSampler is much more performance since you can (and probably should) use InstancedMesh
Additionally you can use this library to generate only the positions
- Multi-models: https://stackblitz.com/edit/vitejs-vite-kebufehm?file=package.json
- Animated models: https://stackblitz.com/edit/vitejs-vite-7fz6pccr?file=src%2Fmain.js
- TresJs: https://stackblitz.com/edit/vitejs-vite-qpspyyen?file=src%2Fcomponents%2FTheExperience.vue
import { ThreeScatter } from 'three-scatter'
// Count: Number of samples
// Surface: Geometry from which to sample
// Model: 3D model or models to scatter
const scatter = new ThreeScatter(count, surface, model);
scene.add(scatter);
You can also scatter more than one model:
const scatter = new ThreeScatter(count, surface, [model1, model2]);
three-scatter
comes with lots of handy method for you, one of the most common ones is setAll
that allow you affect all the scattered models.
const scatter = new ThreeScatter(count, surface, [model1, model2, model3]);
scatter.setAll((model, index) => {
model.scale.set(0.1, 0.1, 0.1);
});
If you don't need ThreeScatter
handle your models you can instantiate the class without any models, then get the positions:
const scatter = new ThreeScatter(count, surface);
const positions = scatter.getPositions()
you can still get different positions using the setSeeds
method but you have to update your models manually.
NOTE: Using this approach means that no other internal method will have effects in your model
scatter.setSeeds(5); // tweak it and find the right value for you
// This method will align Y+up with the normals of the surface
scatter.alignToSurfaceNormal();
// This method will remove the model that has collisions with other scattered model
scatter.removeCollisions();
// Dispose all the geometries and material and remove all the meshes
scatter.cleanGroup();
// return all the faces of the surface sample, using a Triangle: https://threejs.org/docs/?q=triangle#api/en/math/Triangle
scatter.getFaces();
// return all the positions, useful if you want to display specifics positions in your scene
scatter.getPositions();
ThreeScatter allows you more control using optional parameters.
const scatter = new ThreeScatter(count, surface, model, {
seeds<number>: 1, // seed to begin with
useSkeletonUtils<boolean>: true // Necessary when you are scattering 3D models with rigging/animations
randomFn<() => number>: Math.random() // if you want to have control over the random function, has to return a value from 0 to 1
});
ThreeScatter
comes with a debug mode that will replace all your models with a low poly mesh, and find the right position, easily.
const scatter = new ThreeScatter(count, surface, model, {
debug<boolean>: true,
debugGeometry<Geometry>: new THREE.SphereGeometry(0.5, 3, 2) ,
debugMaterial<Material>: new THREE.MeshBasicMaterial({ color: 0x800080 }),
});
You can also use the setDebug
and removeDebug
methods to control it after ThreeScatter
is instantiated
scatter.setDebug(); // or
scatter.removeDebug();
You can now set the percentage of model distribution in case you are scattering more than one model.
const scatter = new ThreeScatter(count, surface, [model1, model2], {
distribution: [ 0.25, 0.75]
});
NOTE: In order to set the distribution property, you need to have:
- An array of models
- A
distribution
property with equal length than the array of model - All the numbers inside the
distribution
property needs to sum 1
- Distribution (when more than one model to scatter) should be base on %
- [] Distribution by axis (base on the normals)
- [] Avoid corners
- [] Density
- [] Merge geometries?
- [] Clusters
We are open to contributions, please read the contributing guide to get started.
Be the first to support this project here