Creating A Point Cloud System

To create an empty PCS requires three parameters; its name, the size for every particle and the scene, for example

var pcs = new BABYLON.PointsCloudSystem("pcs", 5, scene);

After creating the PCS there are a number of options for adding particles

Add Points

By default point particles are randomly added within a unit cube.

pcs.addPoints(10000);

will add 10000 points.

  • Adding Point Cloud Points

You can use your own function as a second parameter to set particle properties such as position and color. This function must have this kind of signature:

var myFunc = function (particle, i, s) {
// particle is the current particle, the i-th one in the PCS and the s-th one in its group
};

For example using i;

var myfunc = function (particle, i, s) {
particle.position = new BABYLON.Vector3(0.5 + 0.25 * Math.random(), i / 5000, 0.25 * Math.random());
particle.color = new BABYLON.Color4(Math.random(), Math.random(), Math.random(), Math.random());
};
pcs.addPoints(10000, myfunc);
pcs.addPoints(10000, myfunc);

will produce a tall block of points whose heights cover the full range of 20000 points. Whereas using s,

var myfunc = function (particle, i, s) {
particle.position = new BABYLON.Vector3(0.5 + 0.25 * Math.random(), s / 5000, 0.25 * Math.random());
particle.color = new BABYLON.Color4(Math.random(), Math.random(), Math.random(), Math.random());
};
pcs.addPoints(10000, myfunc);
pcs.addPoints(10000, myfunc);

will produce a denser block of points whose heights only cover a range of 10000 points, as you can see in the picture below.

use of i or s

In addition the use of particle.groupId can have an effect on all particles within a group. For example

var myfunc = function (particle, i, s) {
particle.position = new BABYLON.Vector3(particle.groupId * 0.5 + 0.25 * Math.random(), i / 5000, 0.25 * Math.random());
particle.color = new BABYLON.Color4(Math.random(), Math.random(), Math.random(), Math.random());
};
pcs.addPoints(10000, myfunc);
pcs.addPoints(10000, myfunc);

will displace the second group of points along the x axis.

use groupId

  • Pass A Function

Add Surface / Volume Points

You are able to take a mesh such as this one as a model

Points 3

and convert it to particle points on its surface or within its volume

Points 4

The points are evenly randomly distributed based on the size of the individual triangular facets of the mesh model. The density of points is the same for all facets.

For both the surface and the volume the default is that the points are randomly colored. For example the following are equivalents for the two surface and two volume additions.

pcs.addSurfacePoints(model, 10000);
pcs.addSurfacePoints(model, 10000, BABYLON.PointColor.Random);
pcs.addVolumePoints(model, 10000);
pcs.addVolumePoints(model, 10000, BABYLON.PointColor.Random);

Note: additional calculations in addVolumePoint means that it takes longer than addSurfacePoints for the same number of points. For a large number of points this can be noticeable.

There are four available methods for coloring the points.

MethodEffect
Method
BABYLON.PointColor.Random
Effect
Colors are assigned randomly to each point, default method .
Method
BABYLON.PointColor.Stated
Effect
This method requires two extra parameters, the base color to use, default white, plus a range from 0 to 1 to randomize both the shade and tone of the stated color. A value of 0, default, gives no variation and 1 the largest variation.
Method
BABYLON.PointColor.Color
Effect
When the model has a texture material applied the color of each point is determined by the texture color of a matching point on a facet. When the material used has color but no texture then the material color is used. When the model has no material applied random coloring is used.
Method
BABYLON.PointColor.UV
Effect
The model uv values for each facet corner are used to determine the uv values for the points. An emissive texture can be applied to the pcs.mesh.material to color the PCS mesh

For example:

pcs.addSurfacePoints(box, 1000, BABYLON.PointColor.Stated, new BABYLON.Color3(1, 0, 0), 0.5);
pcs.addVolumePoints(box, 10000, BABYLON.PointColor.Color);
pcs.addSurfacePoints(box, 100000, BABYLON.PointColor.UV);

Note: Using BABYLON.PointColor.UV can be limiting. Several models can be added to the PCS. These models may all have different textures. However only one emissive texture can be applied to a PCS mesh. In this case a separate PCS mesh is needed for each model. This is not a restriction when using BABYLON.PointColor.Color.

Imported Models and Multiple Textures In some cases (for example PBRMaterial) more than one texture can be applied to a model. In which case adding surface or volume points with BABYLON.PointColor.Color will, by default, use the first in the model's texture array. Though often it is, the first texture may not be the color map, for example it may be a normal map. To specify which texture to use its position in the texture array can be added as a second parameter.

pcs.addSurfacePoints(model, 10000, BABYLON.PointColor.Color, 1);
pcs.addVolumePoints(model, 10000, BABYLON.PointColor.Color, 3);

Of course when you import a model you may not know how many child meshes the model is made up off nor the order of textures for each mesh. Using the inspector you can check the loaded textures and see if their names give you a clue. If not then use trial and error from 0 to the number of textures. Alternatively you can check out meshes and textures once loaded along the lines of

BABYLON.SceneLoader.ImportMesh("", "location", "file", scene, function (meshes) {
var n = meshes.length;
var p;
var t;
for (var i = 0; i < n; i++) {
if (meshes[i].material !== null) {
console.log("Mesh", i);
t = meshes[i].material.getActiveTextures();
p = t.length;
for (var j = 0; j < p; j++) {
console.log("Texture", j, "Name", t[j].name);
}
}
}
});

Examples

  • Random Surface
  • Stated Surface
  • Surface Color from Mesh Color
  • Surface Color from Mesh Texture
  • Surface UV from Mesh Texture
  • Surface Color from Imported Mesh Texture
  • Random Volume
  • Stated Volume
  • Volume Color from Mesh Color
  • Volume Color From Mesh Texture
  • Volume UV from Mesh Texture
  • Volume Color From Imported Mesh Texture

Building the Mesh

The PCS mesh cannot be built until all relevant data is collected. Since this can involve ensuring that the material, applied to a model used in adding surface or volume points, is fully loaded, building the mesh is an asynchronous process.

For example when a mesh model is used in determining the points the model cannot be disposed of until the process of PCS construction is completed. This is achieved by, for example

pcs.addSurfacePoints(box, 10000, BABYLON.PointColor.Color);
pcs.addPoints(10000, myFunc);
pcs.buildMeshAsync().then(() => box.dispose());

If you never want the particle properties of your PCS to change, ie you want it to be immutable then you need do no more. Alternatively you can set the PCS as immutable on creation by setting the updatable option. (Currently updatable is the only item in the option list that is available but the option list is open for future expansions)

var pcs = new BABYLON.PointsCloudSystem("pcs", 5, scene, { updatable: false });

After making updatable false the following methods will no longer have any effect, initParticles(), updateParticle(particle) and setParticles().