Wednesday, January 30, 2013

No Joy with a Three.js DOM Event Library

‹prev | My Chain | next›

I was able to get a fairly decent click-and-drag implementation for Three.js in place yesterday. Most of the complication came from translating page coordinates into Three.js coordinates. Which is to say that it was not that complicated. Still, it might be a bit much for kids—both typing and one too many concepts. So tonight I hope to find something a little more the speed for 3D Game Programming for Kids.

Jerome Etienne has a repository with interesting and useful Three.js extensions. Among the extensions is a DOM event library that might be just what I need.

I start by adding the DOM event library to my game with a <script> tag:
<script src="https://raw.github.com/jeromeetienne/threex/master/threex.domevent.js"></script>

In the game, I would like for the player to click and drag ramps around the screen to make reaching goals possible:


So I add an event listener for one of the ramps:
  ramp1.addEventListener('mousedown', function(object3d){ 
    console.log("mousedown ramp1");
  });
But, when I try to click on the ramp, I get nothing—no console output at all.

Instead, I try the alternative syntax in which events are added to a DOM event object:
  var domEvent = new THREEx.DomEvent(camera);
  domEvent.bind(ramp1, 'click', function() {console.log("click ramp1")});
Unfortunately, I still see no output when I click on the ramp or anywhere else in the game.

It is possible that this library is too old for the version of Three.js that I am using (r52). It is also possible that this library does not work with Physijs (objects susceptible to physics simulation) meshes. To test the latter theory, I add a plain old Three.js mesh to the scene, along with an event handler:
  var ball = new THREE.Mesh(
    new THREE.SphereGeometry(100),
    new THREE.MeshNormalMaterial()
  );
  scene.add(ball);
  ball.addEventListener('click', function() {console.log("clicked the three.js ball");});
Unfortunately, this still does not work. Not only do I not see the desired click message logged, but I am seeing errors:
Uncaught TypeError: Cannot read property 'projectionMatrixInverse' of null Three.js:3699
Uncaught TypeError: Cannot read property 'projectionMatrixInverse' of null Three.js:3699
Uncaught TypeError: Cannot read property 'projectionMatrixInverse' of null Three.js:3699
...
Bummer.

So it seems that this library may be a bit too old. I think this is probably a good place to call it a night. I will sleep on the decision to attempt a fix for this (or possibly sticking with last night's solution).


Day #646

2 comments:

  1. Hi! Check https://github.com/jeromeetienne/threex/issues/16


    You have to add THREE.Object3D._threexDomEvent.camera(camera);

    Enjoy! :)

    ReplyDelete
  2. The following post has the full instructions for getting threex-domevent working with the current version of Three.js:

    http://learningthreejs.com/blog/2012/01/17/dom-events-in-3d-space/#comment-802169267

    1) include threex.domevent.object3d.js (in the repo) after threex.domevent.js,
    2) add "THREE.Object3D._threexDomEvent.camera(camera);" after setting up the camera,
    3) open up threex.domevent.js,
    4) replace both instances of vector.subSelf with vector.sub and both instances of THREE.Ray with THREE.Raycaster

    ReplyDelete