title: How to click an object in THREE.js
body: <p>I'm working my way through <a href="http://www.amazon.co.uk/Game-Development-Three-js-Isaac-Sukin/dp/1782168532" rel="nofollow noreferrer">this book</a>, and I'm doing okay I guess, but I've hit something I do not really get. </p>
  
  <p>Below is how you can log to the console and object in 3D space that you click on:</p>
  
  <pre><code>renderer.domElement.addEventListener('mousedown', function(event) {
      var vector = new THREE.Vector3(
          renderer.devicePixelRatio * (event.pageX - this.offsetLeft) / this.width * 2 - 1,
          -renderer.devicePixelRatio * (event.pageY - this.offsetTop) / this.height * 2 + 1,
          0
      );
  
      projector.unprojectVector(vector, camera);
  
      var raycaster = new THREE.Raycaster(
          camera.position,
          vector.sub(camera.position).normalize()
      );
  
      var intersects = raycaster.intersectObjects(OBJECTS);
      if (intersects.length) {
          console.log(intersects[0]);
      }
  }, false);
  </code></pre>
  
  <p>Here's the book's explanation on how this code works:</p>
  
  <blockquote>
    <p>The previous code listens to the mousedown event on the renderer's canvas. </p>
  </blockquote>
  
  <p>Get that, we're finding the domElement the renderer is using by using <code>renderer.domElement</code>. We're then binding an event listener to it with <code>addEventListner</code>, and specifing we want to listening for a <code>mousedown</code>. When the mouse is clicked, we launch an anonymous function and pass the <code>event</code>variable into the function.</p>
  
  <blockquote>
    <p>Then,
    it creates a new Vector3 instance with the mouse's coordinates on the screen
    relative to the center of the canvas as a percent of the canvas width.</p>
  </blockquote>
  
  <p>What? I get how we're creating a new instance with <code>new THREE.Vector3</code>, and I get that the three arguments <code>Vector3</code> takes are its <code>x, y and z</code> coordinates, but that's where my understanding completely and utterly breaks down.</p>
  
  <p>Firstly, I'm making an assumption here, but to plot a vector, surely you need two points in space in order to project? If you give it just one set of coords, how does it know what direction to project from? My guess is that you actually use the <code>Raycaster</code> to plot the "vector"...</p>
  
  <p>Now onto the arguments we're passing to <code>Vector3</code>... I get how <code>z</code> is 0. Because we're only interested in where we're clicking on the screen. We can either click up or down, left or right, but not into or out of the screen, so we set that to zero. Now let's tackle x:</p>
  
  <pre><code>renderer.devicePixelRatio * (event.pageX - this.offsetLeft) / this.width * 2 - 1,
  </code></pre>
  
  <p>We're getting the PixelRatio of the device, timsing it by where we clicked along the x axis,  dividing by the renderer's domElement width, timsing this by two and taking away one.</p>
  
  <p>When you don't get something, you need to say what you do get so people can best help you out. So I feel like such a fool when I say:</p>
  
  <ul>
  <li>I don't get why we even need the pixel ratio I don't get why we times that by where we've clicked along the x </li>
  <li>I don't get why we divide that by the width </li>
  <li>I <em>utterly</em> do not get why we need to times by 2 and take away 1. Times by 2, take away 1. That could genuinely could be times by an elephant, take away peanut and it would make as much sense.</li>
  </ul>
  
  <p>I get <code>y</code> even less:</p>
  
  <pre><code>-renderer.devicePixelRatio * (event.pageY - this.offsetTop) / this.height * 2 + 1,
  </code></pre>
  
  <p>Why are we now randomly using <code>-</code>devicePixelRatio? Why are now deciding to <code>add</code> one rather than <code>minus</code> one?</p>
  
  <blockquote>
    <p>That vector is then un-projected (from 2D into 3D space) relative to the camera.</p>
  </blockquote>
  
  <p>What?</p>
  
  <blockquote>
    <p>Once we have the point in 3D space representing the mouse's location,
    we draw a line to it using the Raycaster. The two arguments that it
    receives are the starting point and the direction to the ending point.</p>
  </blockquote>
  
  <p>Okay, I get that, it's what I was mentioning above. How we need two points to plot a "vector". In THREE talk, a vector appears to be called a "raycaster".</p>
  
  <p>However, the two points we're passing to it as arguments don't make much sense. If we were passing in the camera's <code>position</code> and the vector's <code>position</code> and drawing the projection from those two points I'd get that, and indeed we are using the <code>camera.position</code> for the first points, but</p>
  
  <pre><code>vector.sub(camera.position).normalize()
  </code></pre>
  
  <p>Why are we subtracting the camera.position? Why are we normalizing? Why does this useless f***** book not think to explain anything?</p>
  
  <blockquote>
    <p>We get the direction by subtracting the mouse and camera positions and
    then normalizing the result, which divides each dimension by the
    length of the vector to scale it so that no dimension has a value
    greater than 1.</p>
  </blockquote>
  
  <p>What? I'm not being lazy, not a word past <code>by</code> makes sense here.</p>
  
  <blockquote>
    <p>Finally, we use the ray to check which objects are located in the
    given direction (that is, under the mouse) with the intersectObjects
    method. OBJECTS is an array of objects (generally meshes) to check; be
    sure to change it appropriately for your code. An array of objects
    that are behind the mouse are returned and sorted by distance, so the
    first result is the object that was clicked. Each object in the
    intersects array has an object, point, face, and distance property.
    Respectively, the values of these properties are the clicked object
    (generally a Mesh), a Vector3 instance representing the clicked
    location in space, the Face3 instance at the clicked location, and the
    distance from the camera to the clicked point.</p>
  </blockquote>
  
  <p>I get that. We grab all the objects the vector passes through, put them to an array in distance order and log the first one, i.e. the nearest one:</p>
  
  <pre><code>console.log(intersects[0]);
  </code></pre>
  
  <p>And, in all honestly, do you think I should give up with THREE? I mean, I've gotten somewhere with it certainly, and I understand all the programming aspects of it, creating new instances, using data objects such as arrays, using anonymous functions and passing in variables, but whenever I hit something mathematical I seem to grind to a soul-crushing halt.</p>
  
  <p>Or is this actually difficult? Did you find this tricky? It's just the book doesn't feel it's necessary to explain in much detail, and neither do <a href="https://stackoverflow.com/questions/19425326/three-js-click-object">other</a> <a href="https://stackoverflow.com/questions/7956442/detect-clicked-object-in-three-js">answers</a> , as though this stuff is just normal for most people. I feel like such an idiot. Should I give up? I want to create 3D games. I really, really want to, but I am drawn to the poetic idea of creating an entire world. Not math. If I said I didn't find math difficult, I would be lying.</p>