> Learn how to create a point cloud system in Babylon.js.

Source: https://doc.babylonjs.com/features/featuresDeepDive/particles/point_cloud_system/pcs_creation

# PCS Creation

Creating an empty PCS requires three parameters: its name, the size of every particle, and the scene. For example:

```javascript
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.

```javascript
pcs.addPoints(10000);
```

will add 10000 points.

- [Playground: Adding Point Cloud Points](https://playground.babylonjs.com/#UI95UC) - Simple example of 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 a signature like this:

```javascript
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`:

```javascript
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 20,000 points. By contrast, using `s`:

```javascript
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 cover only a range of 10,000 points, as you can see in the picture below.

![use of i or s](https://doc.babylonjs.com/img/how_to/particles/points1.webp)

In addition, the use of `particle.groupId` can affect all particles within a group. For example:

```javascript
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](https://doc.babylonjs.com/img/how_to/particles/points2.webp)

- [Playground: Pass A Function](https://playground.babylonjs.com/#UI95UC#1) - Simple example of passing a function to add point cloud points.

## Add Surface / Volume Points

You can use a mesh such as this one as a model

![Points 3](https://doc.babylonjs.com/img/how_to/particles/points3.webp)

and convert it to particle points on its surface or within its volume.

![Points 4](https://doc.babylonjs.com/img/how_to/particles/points4.webp)

The points are evenly and 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 surface and volume, the default is for the points to be colored randomly. For example, the following are equivalent for the two surface additions and the two volume additions.

```javascript
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` mean 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.

| Method                    | Effect                                                                                                                                                                                                                                                                                    |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BABYLON.PointColor.Random | Colors are assigned randomly to each point; this is the default method.                                                                                                                                                                                                                              |
| BABYLON.PointColor.Stated | This method requires two extra parameters: the base color to use (white by default) and a range from 0 to 1 to randomize both the shade and tone of the stated color. A value of 0, the default, gives no variation, and 1 gives the largest variation.                                                |
| BABYLON.PointColor.Color  | When the model has a texture material applied, the color of each point is determined by the texture color at the matching point on a facet. When the material used has color but no texture, the material color is used. When the model has no material applied, random coloring is used. |
| BABYLON.PointColor.UV     | 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:

```javascript
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 that case, adding surface or volume points with `BABYLON.PointColor.Color` will, by default, use the first texture in the model's texture array. Although that is often the color map, it may instead be a normal map. To specify which texture to use, add its position in the texture array as a second parameter.

```javascript
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 it is made up of, nor the order of textures for each mesh. Using the [inspector](https://doc.babylonjs.com/toolsAndResources/inspectorv2), you can check the loaded textures and see whether their names give you a clue. If not, use trial and error from 0 to the number of textures. Alternatively, you can inspect meshes and textures once loaded along the lines of

```javascript
BABYLON.ImportMeshAsync("location" + "file", scene).then(function ({ meshes }) {
  var n = meshes.length;
  var p;
  var t;
  for (let i = 0; i < n; i++) {
    if (meshes[i].material !== null) {
      console.log("Mesh", i);
      t = meshes[i].material.getActiveTextures();
      p = t.length;
      for (let j = 0; j < p; j++) {
        console.log("Texture", j, "Name", t[j].name);
      }
    }
  }
});
```

**Examples**

- [Playground: Random Surface](https://playground.babylonjs.com/#UI95UC#2) - Simple example of a point cloud system with random surfaces.
- [Playground: Stated Surface](https://playground.babylonjs.com/#UI95UC#3) - Simple example of a point cloud system with stated surfaces
- [Playground: Surface Color from Mesh Color](https://playground.babylonjs.com/#UI95UC#4) - Simple example of a point cloud system with surface color from mesh color.
- [Playground: Surface Color from Mesh Texture](https://playground.babylonjs.com/#UI95UC#5) - Simple example of a point cloud system with surface color from mesh texture.
- [Playground: Surface UV from Mesh Texture](https://playground.babylonjs.com/#UI95UC#6) - Simple example of a point cloud system with surface UV from mesh texture.
- [Playground: Surface Color from Imported Mesh Texture](https://playground.babylonjs.com/#UI95UC#28) - Simple example of a point cloud system with surface color from an imported mesh texture.
- [Playground: Random Volume](https://playground.babylonjs.com/#UI95UC#7) - Simple example of a point cloud system with random volume.
- [Playground: Stated Volume](https://playground.babylonjs.com/#UI95UC#8) - Simple example of a point cloud system with stated volume.
- [Playground: Volume Color from Mesh Color](https://playground.babylonjs.com/#UI95UC#9) - Simple example of a point cloud system with volume color from mesh color.
- [Playground: Volume Color From Mesh Texture](https://playground.babylonjs.com/#UI95UC#10) - Simple example of a point cloud system with volume color from a mesh texture.
- [Playground: Volume UV from Mesh Texture](https://playground.babylonjs.com/#UI95UC#11) - Simple example of a point cloud system with volume UV from a mesh texture.
- [Playground: Volume Color From Imported Mesh Texture](https://playground.babylonjs.com/#UI95UC#28) - Simple example of a point cloud system with volume color from an imported mesh texture.

## Building the Mesh

The PCS mesh cannot be built until all relevant data is collected. Because this can involve ensuring that the material applied to a model used for adding surface or volume points is fully loaded, building the mesh is an asynchronous process.

For example, when a mesh model is used to determine the points, the model cannot be disposed of until PCS construction is complete. This can be achieved as follows:

```javascript
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, that is, you want it to be immutable, then you do not need to do anything more. Alternatively, you can set the PCS as immutable when you create it by setting the `updatable` option. (Currently, `updatable` is the only available item in the options list, but the list is open to future expansion.)

```javascript
var pcs = new BABYLON.PointsCloudSystem("pcs", 5, scene, { updatable: false });
```

After setting `updatable` to false, the following methods will no longer have any effect: `initParticles()`, `updateParticle(particle)`, and `setParticles()`.
