← cad viewer

CAD viewer · #5

Face picking: mesh in the front, B-rep in the back

Click a face in /viewer and it highlights — the whole face, not the triangle under your cursor. That distinction is the difference between a mesh viewer and a CAD viewer, and it's the first feature here that uses real B-rep data.

The mapping

occt-import-js doesn't just return triangle soup — each mesh comes with brep_faces, an array of { first, last } ranges. The ranges index into the triangle buffer: face 2 of a body might be triangles 22–57 of that mesh's index array.

So picking is three lookups, no geometric detective work:

click → raycast → hit.faceIndex  (which triangle)
     → find range in brep_faces containing it  (which B-rep face)
     → rebuild a highlight mesh from that index subrange  (draw it)

The highlight geometry shares the part's position/normal buffers and takes a subarray view of the index — the whole selection is zero-copy:

geometry.setAttribute('position', src.attributes.position);
geometry.setAttribute('normal', src.attributes.normal);
geometry.setIndex(new THREE.BufferAttribute(
  part.index.subarray(face.first * 3, (face.last + 1) * 3), 1,
));
const mesh = new THREE.Mesh(geometry, highlightMaterial);

Accent color, polygonOffset to win the depth test, gone when you click empty space.

The detail that took the longest

Raycasts and orbit drags both start with a mouse press. Selection only fires on clicks under 5px of pointer movement — anything more is an orbit. Invisible details like that are most of the work in a tool that feels right.

Also: the status line now reports face area, computed by summing triangle cross-products. mm² or cm² depending on magnitude — a small taste of the measurement features to come.