Skip to main content

Mesh Detection

Interaction between real-world and virtual objects is achieved via visual and logical interactions between the two. Mesh detection is an API that provides access to the representation of real-world geometry in the form of meshes. It can be used in a number of ways such as:

  • Virtual object physics within a real-world environment
  • Path finding
  • Object placement
  • Occlusion
  • Procedural effects

This API provides a list of meshes, their geometry, transformation and semantic labeling.

The underlying system can provide pre-captured data as well as provide real-time reconstruction depending on the underlying system implementation.

Support​

if (app.xr.meshDetection.supported) {
// mesh detection is supported
}

app.xr.on('start', () => {
if (app.xr.meshDetection.available) {
// mesh detection is available
}
});

Access​

A feature flag needs to be added to the session start:

app.xr.start(camera, pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, {
meshDetection: true
});

Meshes are added/removed asynchronously:

app.xr.meshDetection.on('add', (xrMesh) => {
// a new XrMesh has been added

xrMesh.once('remove', () => {
// an XrMesh has been removed
});
});

Also, the list of XrMeshes is available:

const xrMeshes = app.xr.meshDetection.meshes;
for (let i = 0; i < xrMeshes.length; i++) {
const xrMesh = xrMeshes[i];
}

Mesh​

Each mesh is represented as an instance of XrMesh, which can be added/removed during an active session. It also has data that can be changed during its lifetime.

You can access the position and rotation (world-space) of an XrMesh:

entity.setPosition(xrMesh.getPosition());
entity.setRotation(xrMesh.getRotation());

Each XrMesh has its vertices and indices (in local-space), that can be used to construct a visual mesh. An example below creates a visual mesh for each XrMesh and adds it to the root of the scene:

app.xr.meshDetection.on('add', (xrMesh) => {
// geometry data
const mesh = new pc.Mesh(app.graphicsDevice);
mesh.clear(true, true); // ensure that mesh is created with dynamic buffers
mesh.setPositions(xrMesh.vertices); // set vertices
mesh.setNormals(pc.calculateNormals(xrMesh.vertices, xrMesh.indices)); // calculate normals
mesh.setIndices(xrMesh.indices); // set indices
mesh.update(pc.PRIMITIVE_TRIANGLES); // update buffers

const material = new pc.StandardMaterial();
const meshInstance = new pc.MeshInstance(mesh, material);

const entity = new pc.Entity();

// add render component
entity.addComponent('render', {
meshInstances: [ meshInstance ]
});

// add entity to the scene root
app.root.addChild(entity);

// clean up after XrMesh is removed
xrMesh.once('remove', () => {
material.destroy();
mesh.destroy();
entity.destroy();
});
});

Semantic Label​

XrMesh can represent various real-world objects and a label can help to identify what it represents using its property XrMesh.label.

These labels can be any of: floor, wall, door, window, table, screen, global mesh, other, and more. Here is a list of semantic labels, although this list is not definitive and the platform can report anything it feels fit.

Changes​

Depending on the underlying system capabilities, the XrMesh geometry can change while an XR session is active. You can subscribe to that event and update a visual mesh accordingly:

xrMesh.on('change', () => {
// vertices, indices and/or label has been changed
});