TODO: definition of picking
xeometry supports four types of picking:
- pick object at canvas coordinates,
- pick point on object surface at canvas coordinates,
- pick object with World-space ray, and
- pick point on object surface with World-space ray.
Types 1 and 3 just return the ID of the picked object.
Types 2 and 4 return the picked object, as well as information about the surface intersection, which includes:
- the triangle,
- barycentric coordinates within the triangle,
- World space coordinates,
- View space coordinates,
- normal vector, and
- UV coordinates.
Note that we'll only get a normal if the object's geometry has normals, and UV coordinates if the geometry has UVs. xeometry finds the values for these by interpolating within the values for the triangle vertices using the barycentric coordinates.
_Under the hood: this article explains the picking algorithms used in xeogl (xeometry's underlying WebGL engine): _http://xeolabs.com/articles/xeogl-picking
This type of picking is the simplest: we pick the closest object behind the given canvas coordinates. This is equivalent to firing a ray through the canvas, down the negative Z-axis, to find the first object it hits.
Draw outline around each clicked object (see Outlining Objects):
viewer.getOverlay().addMouseEventListener("mouseclick", function(e) {
var hit = viewer.pickObject([e.x, e.y]);
if (hit) {
var objectId = hit.id;
viewer.showOutline(objectId);
}
});
Hide each clicked object (see Visibility):
viewer.getOverlay().addMouseEventListener("mouseclick", function(e) {
var hit = viewer.pickObject([e.x, e.y]);
if (hit) {
var objectId = hit.id;
viewer.showOutline(objectId);
}
});
Fit camera view to each clicked object (see Fitting Things in View):
viewer.getOverlay().addMouseEventListener("mouseclick", function(e) {
var hit = viewer.pickObject([e.x, e.y]);
if (hit) {
var objectId = hit.id;
viewer.viewFit(objectId);
}
});
Like the previous type of picking, this one also picks the closest object behind the given canvas coordinates, but also gets geometric information about the point on the object's surface that lies right behind those canvas coordinates.
Annotate an object by clicking on it (see Creating Annotations):
viewer.getOverlay().addMouseEventListener("mouseclick", function(e) {
var hit = viewer.pickSurface([e.x, e.y]);
if (hit) {
viewer.createAnnotation("annot_" + Date.now(), { // Ensure 'unique' ID
objectId: hit.id,
primIndex: hit.primIndex,
bary: hit.bary,
glyph: "A1",
title: "My annotation",
desc: "Description of the annotation",
eye: viewer.getEye(),
look: viewer.getLook(),
up: viewer.getUp(),
occludable: true
pinShown: true,
labelShown: true
});
}
});
For this type of picking, xeometry fires a ray through the scene, in World-space, to pick the first entity it hits.
Firing a ray through World space to outline the first object that intersects it (see Outlining Objects):
var hit = viewer.rayCastObject([0,0,-100], [0,0,1]); // Origin, dir
if (hit) {
var objectId = hit.id;
viewer.showOutline(objectId);
}
Like the previous type of picking, this one also involves firing a ray through the scene in World-space, to pick an object, but this time we're also getting geometric information about the intersection of the ray with the entity surface.
Getting object and surface intersection with a World-space ray:
hit = viewer.rayCastSurface([0,0,-100], [0,0,1]); // Origin, dir
if (hit) {
var worldPos = hit.worldPos;
console.log("object raycasted: " + hit.id);
console.log("surface coordinates: "
+ worldPos[0] + "," + worldPos[1] + "," + worldPos[2]);
}
Sometimes we want to be able to pick through things, like windows. We can do this by setting objects unpickable.
Making a couple of objects unpickable:
viewer.setUnpickable(["gearbox#1", "gearbox#1"]);
Making a whole model unpickable:
viewer.setUnpickable("gearbox");
Making objects of given types unpickable (in this case IFC windows and spaces):
viewer.setUnpickable(["IfcWindow", "IfcSpace]);