1

A little context:

I have a scene populated with a reasonably large amounts of objects (non-merged) which have to be individually pickable.

Each of those object is an Object3D with the following structure:

parent Object3D
|_ child_1
|_ child_2
|_ etc

By default and on initial rendering, only child_1s are visible.

Each child_1 is a plane geometry whose quaternion is set to that of the camera, so that it always faces it (similar to a billboard)

The camera is declared as thus:

camera = new THREE.PerspectiveCamera(
 70,
 WIDTH / HEIGHT,
 0.1,
 10000000
);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 500000;
camera.lookAt(new THREE.Vector3( 0, 0, 0 ));
scene.add(camera);

And each child_1 is inserted in the scene like this:

child_1 = new THREE.Mesh(
  new THREE.PlaneGeometry(child_1_scale, child_1_scale),
  new THREE.MeshBasicMaterial({
    map: child_1_texture,
    blending: THREE.AdditiveBlending,
    color: new THREE.Color('rgb('+child_1_data.color.r+','+child_1_data.color.g+','+child_1_data.color.b+')'),
    transparent: true
  })
);

child_1.quaternion = camera.quaternion;
child_1.castShadow = false;
child_1.receiveShadow = false;

parent.add(child_1);

Everything works fine on the very initial rendering frame: the following picking function works.

var pick_object = function(el, coords){

  var mousevector = new THREE.Vector3(
    ( coords.x / $(el).width() ) * 2 - 1,
    -( coords.y / $(el).height() ) * 2 + 1,
    0
  );

  var projector = new THREE.Projector();
  projector.unprojectVector(mousevector, camera);

  var raycaster = new THREE.Raycaster(
    camera.position,
    mousevector.sub(camera.position).normalize()
  );

  var intersects = raycaster.intersectObjects(scene.children, true);

  // one or more hits: we take only the first one that DOES NOT match the ignored entity types for selection (helpers, etc)
  if( intersects.length>0 ){
    for( var i=0, n=intersects.length; i<n; i++ ){
      if (
        picking_ignored_entity_types.indexOf( intersects[i].object.entity_type ) == -1
        && intersects[i].object.visible == true
      ) {
        return intersects[i];
      }
    }
  }

  return null;
};

However, as soon as the (trackball) controls are used to rotate around either:

  • the initial lookAt() or the camera ([0,0,0])
  • or a different set of coordinates (like the center of an object)

then the picking starts to behave badly.

The same is true after panning and, to a lesser extent (but probably for the wrong reasons) after zooming in/out.

My question is: do I need, during or after a rotation, to update a matrix somewhere? Do something else? It's as if the camera was not updated according to the rotation/pan handled by the controls.

Fiddle here :

http://jsfiddle.net/Hal9/TrfpU/

If you play around with the controls, zoom, rotate and pan, I hope you will notice that some "blue squares", when hovered on, do not trigger the red helper appearance. Most of them do, but not all.

Hal
  • 537
  • 4
  • 13
  • 1. What does 'behaves badly' mean? 2. What controls? 3. Create one plane geometry and reuse it; set `mesh.scale` instead. 4. Can you provide a live example with one mesh to demonstrate the problem? – WestLangley Jan 27 '14 at 17:02
  • Thank you WestLangley - I have updated the question with a link that would enable you to run the code locally. The plane geometry is an optimisation that I will put in place later, though. Unless this might be the cause? :) – Hal Jan 27 '14 at 18:02
  • Live link, or jsfidde, with one mesh please, that reproduces the problem. http://jsfiddle.net/9GudA/ – WestLangley Jan 27 '14 at 18:57
  • Fiddle works perfectly for me. What is the 'near` plane set to in your version? Set it to 1 or 10 and see if it works. If so, I will post an answer. Tip: move "new" out of tight loops. Do this instead: `projector.unprojectVector( m, c );` `raycaster.set( c.p, m.sub(c.p).normalize() );` – WestLangley Jan 28 '14 at 14:04

0 Answers0