Unfortunately, three.js’ Ray class currently doesn’t detect intersections with imported Collada objects. Unfortunately, because I heavily rely on imported models and I’m too lazy to do the detection manually.
But, the good new is, the collada objects carry all information needed for the ray caster to work properly; you just need to do some manual tweaking.
Step 1: Modifying the Ray Class
The ray class checks whether the passed object is either a
THREE.Particle or a
THREE.Mesh. Usually, when adding a Collada object to the scene, you add it’s
scene property. And this is not a
THREE.Mesh, it’s a
THREE.Object3D. So we modify the check (in src/core/Ray.js, at the time of writing on line 72):
These are the two things the ray caster needs to do it’s work.
Step 2: Modifying the object added to the scene.
Update: Please check the “Update” section further below.
Let’s assume your callback for the Collada loader looks something like this:
This is where we need to add the geometry object needed for the ray caster. The collada object has a
dae property that contains loads of stuff, including animations, images and cameras. And, there is a
geometries property, this is what we are looking for. It contains all geometries that were found in the xml file, but, sadly, as an object. That means, you need to know the name of your mesh. You can look it up in the file or just check the property name in the console:
Expand it further, and you’ll see a
mesh property, containing a
geometry3js property that holds a
THREE.Geometry instance. Bingo! That’s the one we need. In my case:
Now just add that thing to the object that’s going to be added to the scene:
Step 3: Fun (and profit, maybe)
Now the modified Ray class can detect intersections with the Collada object. Of course, you have to look up the mesh id. And you’d better have only one mesh in your Collada. But given the fact that you’ll probably have a limited amount of imported models and that these should ideally contain only one mesh, this should be a doable task. If you still want an automated approach and do not fear assumptions: Iterate over the geometries object, go into the mesh property of the thing you encounter and return the instance stored in geometry3js:
You could even do that in the Collada loader class. But keep in mind that if you have multiple meshes in the original file you have no idea which one is going to end up in the object; I for one prefer doing it manually during the process of adding the Collada to the scene.
There is another, very convenient way to add the geometry to the object, that also works for Colladas containing multiple meshes. As always, reading the source code just one more time really helps… After loading, the Collada object contains everything that was imported from the XML file in a
children property: Lights, cameras – and the mesh. So what I’m doing now is this:
For large models containing multiple meshes, the results still are a little awkward, but it works reliably for models containing one mesh, and it saves you from looking for the mesh property by hand.
You can also just use the ReusableRay class (I wrote about it here), and don’t have to do anything else. There’s also an example using it to find Collada models by mouse clicks.