Marquee Selection with THREE.js

Tuesday, November 26, 2013 Posted by Josh Staples 1 comments
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:

THREE.js Ray Intersection with a page offset

Posted by Josh Staples 0 comments
One consideration you'll have to make when projecting rays, clicks, swipes or otherwise interacting with the Canvas element is the OFFSET.   The mouse X,Y event clicks need to be adjusted by the Canvas offset.

Here is a demo.

canvasX = mouse.clientX - canvas.offset.left;
canvasY = mouse.clientY -;

If you don't take this offset into consideration, you'll be projecting a ray at the wrong location and won't intersect anything!   Very very frustrating if your code works and you're not getting good results.

Here is a gist of the code offset:
Labels: , , ,

Ray Intersection with THREE.js

Posted by Josh Staples 0 comments

Rays & Intersections

The first step is to create a simple scene with a few cube meshes.

Here is a demo.
    Simple 3D scene with cubes.
    Step 1:  Create a simple scene with cubes

The next step is to add an event listener and callback to deal with the ray projection and like.  Check out the following Gist code here:
Labels: ,

JavaScript and WebGL in the East Bay

Monday, November 25, 2013 Posted by Josh Staples 0 comments

Greetings from the East Bay.  

I am a WebGL JavaScript R&D Software Engineer at Navis, LLC located at Jack London Square in Oakland, California.

Navis provides a software product to shipping terminals around the world.   The Terminal Operating System (TOS) facilitates the organization and movement of shipping containers in over 250 ports around the world.

In short, Navis provide the "smarts" for moving TRILLIONS of dollars worth of cargo around the world.
In WebGL short, we move cubes around the world. :)   Translation and rotation!

Recently I gave a presentation at the WebGL Meetup in San Francisco.

Poorly Converted Slidedeck:

Video of the Presentation:

    NOTE:  The sound and picture at the latter are a bit off as it was filmed via a webcam.

One of reasons I've started this coding blog is to demonstrate some of the work I am doing in JavaScript and WebGL in the East Bay.  In that regard, I hope to provide solid code examples for my fellow WebGL developers.

Feel free to take a look at all of my code at my Github account:

In the near future, I hope to present the following topics:
  1. Ray Intersection
  2. Ray Intersection with a DIV offset.
  3. Marquee Selection of 3D objects (with a DIV offset)
  4. Marquee Selection with caching.

Happy Coding!
- Josh Staples