Marquee Selection with THREE.js

Tuesday, November 26, 2013 Posted by Josh Staples
While click interaction is great, the real bees knees with THREE.js is to drag a selection box around a bunch of meshes.

Before you read further, please take a look at the demo.

EDIT:   I have a new post that demonstrates how to speed up large selections with a cache.  When you finish this article, check out this one as well: Cached Marquee Selection.

So, what data do we drag around and how do we figure out what is selected?

Drag select example

What mechanism do we use to do the selection comparison?

  1. Project a bunch of rays into the scene
    • Pro:
      • Bound to hit something if you pack the rays closely enough
    • Con:
      • Too many rays and objects make this really, really slow
      • Rays packed too loosely will miss some intersections
  2. Unproject 3D coordinate data and do a 2D comparison
    • Pro:
      • Much faster comparison
      • Only unproject the 3D coordinates once (if the scene/camera is static)
    • Con:
      • Limited to point data unless you do a lot more work
So after a little experimentation, unprojecting the 3D data into 2D space and then doing a simple "within bounds" comparison is much, much faster.

In that regard, we have two kinds of data to unproject.   We could use both types but that is too correct of an answer.  For discussion's sake, let's say we can only use a single kind of data.

What coordinate data do we compare to the marquee coordinates?

  1. Centroids
    • Pro: 
      • Single centroid for each mesh
    • Con:
      • You have to drag around the exact center of the mesh
      • Dragging around non-centroid areas will not result in a selection
  2. Vertices
    • Pro:
      • 8 vertices is a lot more data than a single centroid
      • Encapsulates the area of a volume a little better.  You can drag around corners
    • Con:
      • Still not perfect.  You could drag through a mesh and not hit any corners
      • Lots more data.  Might get duplicate intersections

Marquee drag select process:

  1. Detect drag area
    1. Detect the mousedown event location (one corner of the selection rectangle)
    2. Detect the mousemove event location (the other corner of the selection rectangle)
    3. On the mouseup event, record the selection rectangle coordinates and clear the marquee
  2. Unproject all 3D meshes within the scene into 2D canvas coordinates
  3. Compare unprojected 3D coordinates to the marquee selection area
    • The selection area has to take the canvas offset into consideration for this latter comparison
  4. If the unprojected 3D coordinates are within the marquee selection area, the color of the "selected" mesh is changed to a random color
    • The cubes will change colors to illustrate selection
Drag select with THREE.js

Here is a Gist of the process: