Picking in an operator
A viewport operator reading the objects under the pointer, and a raycast of the scene from code (scene.raycaster).
import {
type PointerIntersections, SceneObjectFilters, SetObjectsStateCommand, Viewer, ViewportOperator,
} from '@stereograph/teiaviewer';
import { Raycaster, Vector2 } from 'three';
/**
* An operator: the viewport gives it its pointer events, with the objects under the pointer
* (raycast at the first read, shared by the handlers asking the same).
*/
class PaintOperator extends ViewportOperator {
readonly name = 'PaintOperator';
override onPointerClick(_event: PointerEvent, intersections: PointerIntersections) {
// The first loaded object under the pointer, the others see-through.
const hit = intersections.getFirst(SceneObjectFilters.BimMeshFilter);
if (!hit) {
return;
}
// Undoable.
void new SetObjectsStateCommand(this._viewport.viewer, [hit.object.uuid], {
diffuseColor: 0xe0533d,
}).execute();
}
}
const viewer = new Viewer();
const { viewport } = viewer;
// The operator takes the pointer, until the default one is given back.
viewport.setOperator(new PaintOperator(viewport));
viewport.resetDefaultOperator();
// Picking without pointer: a ray through the centre of the view, every object it hits, sorted
// as seen (highest layer first, then nearest).
const raycaster = new Raycaster();
raycaster.setFromCamera(new Vector2(0, 0), viewport.camera);
const hits = viewer.scene.raycaster.raycast(raycaster.ray, viewport.camera, {
onlyFirst: false,
});
for (const { object, point } of hits) {
console.info(object.uuid, point);
}