Mesh and Vertex Data

The Mesh Class and Its Vertex Data

A Mesh holds a Geometry (Buffers and VAOs's vertex buffers, positions, normals, texture coordinates and optional colors or bone weights, plus indices), a material, and subMeshes, index ranges that can each take a different material; mesh.clone() shares the geometry. getVerticesDataKinds(), getVerticesData(kind), getIndices(), getTotalVertices() and getTotalIndices() read it back.

For a CreateBox book (0.4 x 1 x 0.12 m) they reported position, normal, uv, 24 vertices, 36 indices and one submesh, with positions as a plain Array starting [0.2, -0.5, 0.06, ...]. Each corner appears once per face, with that face's normal, as with Parsing OBJ's OBJ book. Babylon 89,603 keeps this CPU copy for picking and collisions; scene.clearCachedVertexData() frees it (Many Objects), and updatable: true in a builder's options allows updateVerticesData().

A book box's 24 vertices and their normals, read back with getVerticesDataHTMLLive
<!doctype html>
<style>
  body { margin: 0; background: #f7f3ec; font: 13px system-ui, sans-serif; color: #333; }
  canvas { width: 100%; max-width: 600px; height: 330px; display: block; touch-action: none; }
  #info { max-width: 600px; margin: 0; padding: 4px 8px; font-family: monospace; white-space: pre-wrap; }
</style>
<canvas id="view"></canvas>
<pre id="info"></pre>
<script src="https://cdn.jsdelivr.net/npm/babylonjs@9.28.0/babylon.js"></script>
<script>
const canvas = document.getElementById('view');
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
scene.clearColor = BABYLON.Color4.FromHexString('#f7f3ecff');
const camera = new BABYLON.ArcRotateCamera('cam', -Math.PI / 2 - 0.7, 1.1, 2.4, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
camera.useAutoRotationBehavior = true;
new BABYLON.HemisphericLight('sky', new BABYLON.Vector3(0.3, 1, -0.4), scene);

const book = BABYLON.MeshBuilder.CreateBox('book', { width: 0.4, height: 1, depth: 0.12 }, scene);
book.material = new BABYLON.StandardMaterial('cover', scene);
book.material.diffuseColor = BABYLON.Color3.FromHexString('#1f5f8b');
book.material.alpha = 0.55;                          // see the vertices on the far side

// Read the geometry back from the CPU copy Babylon keeps for picking and collisions
const positions = book.getVerticesData(BABYLON.VertexBuffer.PositionKind);
const normals = book.getVerticesData(BABYLON.VertexBuffer.NormalKind);
const lines = [];
const dot = BABYLON.MeshBuilder.CreateSphere('dot', { diameter: 0.035 }, scene);
dot.material = new BABYLON.StandardMaterial('dotMat', scene);
dot.material.emissiveColor = BABYLON.Color3.FromHexString('#e09a10');
for (let i = 0; i < positions.length; i += 3) {
  const p = BABYLON.Vector3.FromArray(positions, i);
  const n = BABYLON.Vector3.FromArray(normals, i);
  // each corner appears three times, once per face, so nudge the dot along its face normal
  dot.createInstance('v' + i / 3).position = p.add(n.scale(0.012));
  lines.push([p, p.add(n.scale(0.18))]);             // the vertex normal
}
dot.isVisible = false;
const normalLines = BABYLON.MeshBuilder.CreateLineSystem('normals', { lines }, scene);
normalLines.color = BABYLON.Color3.FromHexString('#b5452f');

document.getElementById('info').textContent =
  `kinds: ${book.getVerticesDataKinds().join(', ')}\n` +
  `getTotalVertices() ${book.getTotalVertices()}, getTotalIndices() ${book.getTotalIndices()}, ` +
  `subMeshes ${book.subMeshes.length}\n` +
  `positions [${Array.from(positions.slice(0, 6)).map((v) => +v.toFixed(2)).join(', ')}, ...]\n` +
  `indices   [${Array.from(book.getIndices().slice(0, 12)).join(', ')}, ...]`;

engine.runRenderLoop(() => scene.render());
addEventListener('resize', () => engine.resize());
</script>