Select objects and primitives using rays and boundaries
The following class diagrams depict xeokit's picking system architecture.
The SceneObjectsKdTree3 class, a k-d tree that arranges
SceneObjects for
efficient collision testing with boundaries, rays, and frustums, is positioned in the center of the
first diagram. To construct a SceneObjectsKdTree3, use
the collision!createSceneObjectsKdTree3 | createSceneObjectsKdTree3 function.
To find SceneObjects in the SceneObjectsKdTree3 that intersect a 3D world-space ray,
use Picker.rayPick(), which will generate a RayPickResult. To find SceneObjects
that intersect a 2D marquee boundary, use Picker.marqueePick(),
which will generate a MarqueePickResult.
Unpacking the Pick Results
A MarqueePickResult provides a list of SceneObjects that intersect the marquee, so unpacking that is trivial.
On the other hand, a RayPickResult includes comprehensive details regarding
each ray-SceneObject intersection. This information includes everything necessary to inspect the geometry of the intersecting
primitives within each SceneObject, and the coordinates at which each of them intersect the ray.
RayPickResult represents the hierarchical arrangement of Scene components selected by Picker.rayPick(). This
structure enables the iteration of the chosen SceneObjects, and the iteration of the selected Meshes, Geometries, and
GeometryBuckets within each SceneObject. The structure goes all the way down to the chosen primitives, which can be
KdLine3D, KdPoint3D, or KdTriangle3D.
A primitive has one or more vertex indices, and the number of indices is determined by the primitive type. These
indices are used to access the compressed vertex coordinates of the primitive within
SceneGeometryBucket.positionsCompressed. These coordinates can be decompressed using SceneGeometry.positionsDecompressMatrix and
then transformed into the World-space coordinate system using SceneMesh.matrix to obtain the final coordinates of the primitive.
To keep a low memory footprint, while being flexible and extensible, both the RayPickResult and xeokit's
scene graph have been designed in such a way that requires some boilerplate code to traverse and unpack them. This
includes coordinate decompression and transformation, which we'll demonstrate in the example code below.
// And finally within the GeometryBucketHit, a PrimHit // for each primitive that was hit within the SceneGeometryBucket.
// Each PrimtHit wraps a single a single KdPointPrim, KdLinePrim or KdTrianglePrim, // which represents a point, line or triangle primitive, respectively.
// We know the primitive type from the SceneGeometry
switch (geometry.primitive) {
caseTrianglesPrimitive:
// Using the vertex indices of each primitive, // we can then access the compressed coordinates // for that vertex, then we can decompress them // and transform them into World-space.
xeokit Picking System
Select objects and primitives using rays and boundaries
The following class diagrams depict xeokit's picking system architecture.
The SceneObjectsKdTree3 class, a k-d tree that arranges SceneObjects for efficient collision testing with boundaries, rays, and frustums, is positioned in the center of the first diagram. To construct a SceneObjectsKdTree3, use the collision!createSceneObjectsKdTree3 | createSceneObjectsKdTree3 function.
To find SceneObjects in the SceneObjectsKdTree3 that intersect a 3D world-space ray, use Picker.rayPick(), which will generate a RayPickResult. To find SceneObjects that intersect a 2D marquee boundary, use Picker.marqueePick(), which will generate a MarqueePickResult.
Unpacking the Pick Results
A MarqueePickResult provides a list of SceneObjects that intersect the marquee, so unpacking that is trivial.
On the other hand, a RayPickResult includes comprehensive details regarding each ray-SceneObject intersection. This information includes everything necessary to inspect the geometry of the intersecting primitives within each SceneObject, and the coordinates at which each of them intersect the ray.
RayPickResult represents the hierarchical arrangement of Scene components selected by Picker.rayPick(). This structure enables the iteration of the chosen SceneObjects, and the iteration of the selected Meshes, Geometries, and GeometryBuckets within each SceneObject. The structure goes all the way down to the chosen primitives, which can be KdLine3D, KdPoint3D, or KdTriangle3D.
A primitive has one or more vertex indices, and the number of indices is determined by the primitive type. These indices are used to access the compressed vertex coordinates of the primitive within SceneGeometryBucket.positionsCompressed. These coordinates can be decompressed using SceneGeometry.positionsDecompressMatrix and then transformed into the World-space coordinate system using SceneMesh.matrix to obtain the final coordinates of the primitive.
To keep a low memory footprint, while being flexible and extensible, both the RayPickResult and xeokit's scene graph have been designed in such a way that requires some boilerplate code to traverse and unpack them. This includes coordinate decompression and transformation, which we'll demonstrate in the example code below.
Installation
Usage