Level of Details is a powerful tool that was added to BabylonJS in version 2.0 . The concept is rather simple - When the camera is at a certain distance from the mesh, lowering the amount of faces displayed will increase performance without the user noticing the reduction.
LOD requires the developer to add a few meshes to the original mesh. One of the ways to create those meshes is simplification. Many 3D tools offer various simplification algorithms. It is sometimes called Decimation.
Starting Version 2.0, Babylon.js offers an in-browser simplification functionality that works asynchronous while trying not to disturb the rendering process. These LOD levels will be automatically added to the scene after finishing the calculation.
Any object of the class BABYLON.Mesh has a "simplify" function with the following signature:
public simplify(settings: Array<ISimplificationSettings>,
parallelProcessing: boolean = true,
type: SimplificationType = SimplificationType.QUADRATIC,
successCallback?: () => void);
A Simplification-Settings object has two parameters:
A simple example for an array of settings would be:
[{ quality: 0.9, distance: 25, optimizeMesh:true },
{ quality: 0.3, distance: 50, optimizeMesh:true }]
For the typescript users and the "new" lovers, a SimplificationSettings class exists. So, this can also be done:
var settings : Array<ISimplificationSettings> = []; //in JS: var settings = new Array();
settings.push(new BABYLON.SimplificationSettings(0.8, 60));
settings.push(new BABYLON.SimplificationSettings(0.4, 150));
The code runs async. This flag sets the order of processing of each level. If set to true, all will run together. This will use more RAM (for a certain period of time) but will run quicker in general. There is a chance however, that the FPS will be reduced to an unaccepted level due to many parallel calculations between frames. Setting this flag to false will process one setting after the other. This will use only one single simplification object and will use less RAM. It can, however, take a little longer.
To allow further types of simplification to be implemented (will be explained later, for those who are interested) the type of simplification should be stated. There is only one kind at the moment, BABYLON.SimplificationType.QUADRATIC. This is also the default value, if type is undefined.
Since this is an asynchronous function (which returns immediately), a callback is required in order to run code after the simplification process is over.
This function will be called after the Auto-LOD process is successfully done. Not sure in which cases you will require that, but just in case you will - this is how you do it :-)
BABYLON.SceneLoader.ImportMesh("", "./", "DanceMoves.babylon", scene, (newMeshes, particleSystems, skeletons) => {
newMeshes[1].simplify([{ quality: 0.9, distance: 25 }, { quality: 0.3, distance: 50 }],
false, BABYLON.SimplificationType.QUADRATIC, function() {
alert("LOD finisehd, let's have a beer!");
});
});
Zoom in and out to see the effect, watch the number of active vertices closely.
Simplifying spheres. Materials of the spheres will be set after simplification ended completely.
https://www.babylonjs-playground.com/#1ED15P#1 -
Simplifying a color-based complex mesh. An alert window will pop when simplification is over. This mesh will also take time to load and requires optimization.
With global mesh optimization -
https://www.babylonjs-playground.com/#2JBSNA#3 -
With optimization during simplification -
https://www.babylonjs-playground.com/#2JBSNA#4 -
Not all meshes can be simplified. Better said - all meshes can be simplified, some however, should not be.
An object like a Box (if built in an optimal way, like the BABYLON.Mesh.CreateBox function) has no "extra faces" that can be removed. removing one single face will cause it to... not be a box.
(and never forget, rules are meant to be broken!) :
var ground = BABYLON.Mesh.CreateGroundFromHeightMap("ground", "worldHeightMap.jpg", 200, 200, 250, 0, 10, scene, false, function(groundMesh) {
// Add simplify code here
groundMesh.simplify(.......);
});
Due to the nature of Babylon's file format, it is possible that many vertices will have the same positions, normals, but different color/uv information. This presents a problem to the decimation process, which relies on having all triangles with the same position altered.
If you try simplifying a mesh, and it suddenly lacks a few triangles, this will be the reason - your mesh is not "optimized" for simplification.
There are two types of optimization available:
mesh.optimizeIndices(function() {
//do whatever you want here
});
This option alters(!) the mesh's indices order. It is faster, but might change the UV coordinates of vertices of the mesh. If that is the case, use:Check which one of the methods works best for you. Both have their up and down sides, for better results use the 2nd option (set optimizeMesh to true in the settings).
If you want to add a new simplification algorithm, there are a few steps that are required:
You can access the quadratic error decimation directly and play with its features. You can do that by creating an object of the class QuadraticErrorSimplification
var decimator = new QuadraticErrorSimplification(meshToDecimate);
Afterwards you can play with the following object variables:
simplify(settings, successCallback);
See the explanation above to understand what each variable is.