Raycasting vertices of a mesh with three.js - three.js

with threejs i can raycast some meshes that i created like that
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 500 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
//create a triangular geometry
var material = new THREE.MeshBasicMaterial( { color : 0x00cc00 } );
var geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3( -0.5, -0.5, 0 ) );
geometry.vertices.push( new THREE.Vector3( 0.5, -0.5, 0 ) );
geometry.vertices.push( new THREE.Vector3( 0.5, 0.5, 0 ) );
//create a new face using vertices 0, 1, 2
var face = new THREE.Face3( 0, 1, 2 );
//add the face to the geometry's faces array
geometry.faces.push( face );
var object1 = new THREE.Mesh( geometry, material );
scene.add( object1 );
camera.position.z = 10;
//get mouse position
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
//render funciton
function animate() {
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObject( object1 );
if ( intersects.length > 0 ) console.log( intersects );
renderer.render( scene, camera );
}
//run
window.addEventListener( 'mousemove', onDocumentMouseMove, false);
window.addEventListener( 'mousemove', animate, false);
animate();
this line of codes work very well for me. but i want to raycast of indices of this triangular shape instead of all mesh. What should i do?
i tried tihs but it does not work? why?
raycaster.insertObject( object1.geometry.vertices );

Raycaster.intersectObjects documentation
intersects should provide the intersected face, as well as the point of intersection. You can check the distance from the point to a face vertex against a minimum threshold (or simply the closest vertex to point), and return the vertex if it passes.
var iFace = intersects[0].face;
var iPoint = intersects[0].point;
var ab = iFace.a.distanceTo(iFace.b);
var ac = iFace.a.distanceTo(iFace.c);
var bc = iFace.b.distanceTo(iFace.c);
var lambda = Math.min(ab, ac, bc) - 0.1;
if(iFace.a.distanceTo(iPoint) <= lambda){
return iFace.a;
}
if(iFace.b.distanceTo(iPoint) <= lambda){
return iFace.b;
}
if(iFace.c.distanceTo(iPoint) <= lambda){
return iFace.c;
}

Related

Applying postprocessing steps for specific objects

Based on this example i try to create a scene where several objects get the bloom, and other objects dont.
The white cube in the middle is supposed to be just white (without the bloom)
I'm confused on how to get the result that i want. I tried for example adding a 2nd scene with the white cube but it seems i cant get the order right. Maybe my approch with different scenes is wrong?
Whats the "best" way to achieve this behaviour? I always end up just seeing one scene, just the white cube or the 4 colored ones. (example below shows everything atm)
myFiddle: https://jsfiddle.net/qwertasyx/8qw3ys4z/16/
var scene,scene2,camera, controls, pointLight, stats;
var composer, renderer, mixer;
var params = {
exposure: 1,
bloomStrength: 1.5,
bloomThreshold: 0,
bloomRadius: 0
};
var objects = [];
var clock = new THREE.Clock();
var container = document.getElementById( 'container' );
stats = new Stats();
//container.appendChild( stats.dom );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ReinhardToneMapping;
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
//scene2 = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 2.5,2.5, 10 );
scene.add( camera );
// scene2.add( camera );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.maxPolarAngle = Math.PI * 0.5;
controls.minDistance = 1;
controls.maxDistance = 10;
controls.target.set(2.5,2.5,0)
controls.update()
// scene.add( new THREE.AmbientLight( 0x404040 ) );
pointLight = new THREE.PointLight( 0xffffff, 1 );
// camera.add( pointLight );
var renderScene = new THREE.RenderPass( scene, camera );
//var renderScene2 = new THREE.RenderPass( scene2, camera );
var bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
bloomPass.renderToScreen = true;
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;
composer = new THREE.EffectComposer( renderer );
composer.setSize( window.innerWidth, window.innerHeight );
composer.addPass( renderScene );
composer.addPass( bloomPass );
//composer.addPass( renderScene2 );
//objects
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.x += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.x += 5
cube.position.y += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.y += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0x0000ff } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
scene.add( cube );
objects.push(cube)
// cube thats supposed to be not bloomy
var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.y += 2.5
cube.position.x += 2.5
scene.add( cube );
objects.push(cube)
var gui = new dat.GUI();
gui.add( params, 'exposure', 0.1, 2 ).onChange( function ( value ) {
renderer.toneMappingExposure = Math.pow( value, 4.0 );
} );
gui.add( params, 'bloomThreshold', 0.0, 1.0 ).onChange( function ( value ) {
bloomPass.threshold = Number( value );
} );
gui.add( params, 'bloomStrength', 0.0, 3.0 ).onChange( function ( value ) {
bloomPass.strength = Number( value );
} );
gui.add( params, 'bloomRadius', 0.0, 1.0 ).step( 0.01 ).onChange( function ( value ) {
bloomPass.radius = Number( value );
} );
window.onresize = function () {
var width = window.innerWidth;
var height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
composer.setSize( width, height );
};
function animate() {
requestAnimationFrame( animate );
objects.forEach(function(obj){
obj.rotation.z += obj.vrz;
});
stats.update();
composer.render();
}
animate();
I had a similar problem once. An example from this comment helped me.
Note that in that example there are 2 scenes and 2 composers (the final composer gets output of the previous composer as its input)
ppoFinal.blendPass.uniforms.tAdd.value = ppoRGB.composer.renderTarget2.texture;
and render() is called on both composers.
ppoRGB.composer.render();
ppoFinal.composer.render();
This pattern allows you to apply postprocessing effects selectively and it works well. The problem is the scalability of the method and probably performance. Because when you want to apply another object with yet different effect, you need to introduce 3rd scene and 3rd composer. For my little project in the past I ended up with 4 scenes and 4 composers...

Create a planet orbit

i want create a red ring to visualize the Orbit of the green Sphere around the yellow Sphere. With lookat() i have orientate the rings to the green Spheres but i have no idea how i can move the rings in the right angel.
My script:
<!doctype html>
<html>
<head>
</head>
<body>
<div id="container"></div>
<!--Load three.js-->
<script src="js/three.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script>
var camera, controls, scene, renderer, raycaster;
var mouse = new THREE.Vector2();
init();
animate();
function init() {
scene = new THREE.Scene();
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 100000000000000000);
camera.position.z = 30;
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.enableKeys = false;
var planet = ["-4067664386091","-710580828973","-3956610895959","2060000",
"29476716044","5149291420","-46417511315","2660000",
"124056083719","21671373654","16235707106","4810000",
"-107354576606","-18753785170","436797007078","18890000",
"-639929607985","-111789387758","-1118379774141","57970000",
"2907924314427","507985682645","-950946134275","2830000",
"-2275005926406","-397421085828","3223734974754","7480000",
"-4067664386091","-710580828973","-3956610895959","5110000"]
for ( var i = 0; i < 7; i ++ ) {
var geometry = new THREE.SphereGeometry(5, 32, 32);
var material = new THREE.MeshBasicMaterial( {color: 0x09F425} );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = planet[i * 4] / 1000000000;
mesh.position.y = planet[i * 4 + 1] / 1000000000;
mesh.position.z = planet[i * 4 + 2] / 1000000000;
scene.add( mesh );
var startPoint = new THREE.Vector3(0,0,0);
var endPoint = new THREE.Vector3(planet[i * 4] / 1000000000,planet[i * 4 + 1] / 1000000000,planet[i * 4 + 2] / 1000000000);
var direction = new THREE.Vector3().subVectors(endPoint, startPoint).normalize();
var arrow = new THREE.ArrowHelper(direction, startPoint, startPoint.distanceTo(endPoint), 0xCC0000 );
scene.add(arrow);
<!-- I want this red ring in to show the Orbit of the green Spheres -->
var geometry = new THREE.RingGeometry(startPoint.distanceTo(endPoint) - 1, startPoint.distanceTo(endPoint), 32);
var material = new THREE.MeshBasicMaterial( { color: 0xCC0000, side: THREE.DoubleSide } );
var mesh = new THREE.Mesh( geometry, material );
var testPoint = new THREE.Vector3(planet[i * 4] / 1000000000,(planet[i * 4 + 1] / 1000000000)*0.5,planet[i * 4 + 2] / 1000000000);
var pos = new THREE.Vector3();
pos.addVectors(testPoint, mesh.position);
mesh.lookAt(pos);
scene.add(mesh);
<!--------->
}
var geometry = new THREE.SphereGeometry(10, 32, 32);
var material = new THREE.MeshBasicMaterial( {color: 0xCDF409} );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
scene.add( mesh );
window.addEventListener( 'mousemove', onMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onMouseMove( event ) {
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i++ ) {
//intersects[ i ].object.material.color.set( 0xff0000 );
}
renderer.render(scene, camera);
}
</script>
</body>
</html>
If I got you right.
For orbits, there can be a rough solution:
var geometry = new THREE.CircleGeometry(startPoint.distanceTo(endPoint), 128);
geometry.vertices.shift();
geometry.rotateX(-Math.PI / 2);
var material = new THREE.LineBasicMaterial( { color: 0xCC0000 } );
var mesh = new THREE.Line( geometry, material );
and then to align your orbits to their planets:
mesh.lookAt(endPoint); // as you calculated endPoint before, then no need to calculate the same for testPoint
jsfidde example. Clarify, if I missed something from your question.

three.js Mesh not displaying rectangle depending on orientation

I have created a MWE that creates a single rectangle spinning. However, the rectangle disappears based on its orientation, and the material (which claims to be dotted lines) does not work and instead the rectangle is drawn in solid white.
I suspect the disappearance is due to rectangles only being visible facing the camera. Is there a simple two-sided rectangle parameter?
Why isn't the rectangle being drawn as a dashed outline?
var container, stats;
var camera, scene, renderer;
var group;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
function init( ) {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 150, 500 );
scene = new THREE.Scene();
var lineDash = new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 3, gapSize: 1, linewidth: 2 } );
var wall = new THREE.Geometry();
var h = 200;
wall.vertices.push(new THREE.Vector3(0, 0, 0));
wall.vertices.push(new THREE.Vector3(200, 0, 0));
wall.vertices.push(new THREE.Vector3(200, 0, h));
wall.vertices.push(new THREE.Vector3(0, 0, h));
wall.faces.push( new THREE.Face3( 0, 1, 2 ) );
wall.faces.push( new THREE.Face3( 0, 2, 3 ) );
var wallObj = new THREE.Mesh(wall, lineDash );
wallObj.position.x = 0;
wallObj.position.y = 200;
wallObj.rotation.x = Math.PI/2;
group = new THREE.Group();
group.add(wallObj);
scene.add( group );
renderer = new THREE.CanvasRenderer();
renderer.setClearColor( 0xf0f0f0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
group.rotation.y += .05;
renderer.render( scene, camera );
}
init( );
animate();
To make a material double-sided, set
material.side = THREE.DoubleSide.
LineDashedMaterial requires line distances to be computed.
geometry.computeLineDistances().
WebGLRenderer is preferable to CanvasRenderer.
three.js r.75

How can I make three.js update a scene after adding an object or group of objects?

I am fairly new to three.js and have a problem I can't readily find an answer for.
Here is a codepen that should sum up the situation: http://codepen.io/anon/pen/PPYPzO
var container, stats;
var camera, controls, scene, renderer, raycaster, mouse;
init();
animate();
add_world();
var indie_render = true;
for(var j = 0; j < 20; j++){
add_objects(20);
indie_render = !indie_render;
console.log("adding more objects...");
if(!indie_render){render();}
}
function add_world(){
var geometry = new THREE.BoxGeometry( 1000, 1000, 1000);
var mesh = new THREE.MeshBasicMaterial( {color: 0xf5f5dc, wireframe: false, opacity: 0.2, transparent:true } );
var world = new THREE.Mesh( geometry, mesh );
scene.add( world );
render();
}
function add_objects(num, indiv){
var geometry = new THREE.SphereGeometry( 5, 32,32 );
var material = new THREE.MeshBasicMaterial( { shading: THREE.FlatShading } );
material.color.setRGB( Math.random(), Math.random(), Math.random() );
for ( var i = 0; i < num; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
mesh.updateMatrix();
mesh.matrixAutoUpdate = false;
scene.add( mesh );
if(indie_render){
console.log("individual render");
render();
}
}
}
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set(500, 500, -1000);
camera.up.set( 0, 1, 0 );
camera.lookAt(500,500,500);
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
//world
scene = new THREE.Scene();
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( 0x000000, 1 );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
mouse = new THREE.Vector2();
raycaster = new THREE.Raycaster();
container.addEventListener( 'mousemove', onMouseMove, false );
container.addEventListener( 'mousedown', onMouseDown, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}
function onMouseMove( e ) {
mouse.x = ( e.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( e.clientY / renderer.domElement.height ) * 2 + 1;
}
function onMouseDown( e ) {
mouse.x = ( e.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( e.clientY / renderer.domElement.height ) * 2 + 1;
if(e.button == 2){ //right button
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( scene.children, true );
if ( intersects.length > 0 ) {
var geometry = new THREE.SphereGeometry( 5, 32,32 );
var material = new THREE.MeshBasicMaterial( { color:0xff0000, shading: THREE.FlatShading } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(intersects[0].point.x, intersects[0].point.y, intersects[0].point.z);
scene.add(mesh);
render();
}
}
}
In this demo, I init() and animate() a blank scene, and then add a translucent cube, following what seems to be convention. Then I add groups of spheres to the scene in a nested for loop, randomly placing the spheres inside the cube and making a render() call after every scene.add() call.
Currently, the scene adds all the spheres and only then is visible to the user, even though I can add individual objects after the for-loop objects are added (by right-clicking on the cube). I need for the user to be able to watch as spheres are added, rather than waiting for the whole thing to be done.
I realize this may not be the most efficient way to render the scene, but it would be quite helpful if, for example, the info on the objects to be animated is arriving asynchronously from a server. Does anyone have a suggestion?
Thanks
1) First: move call render() to animate:
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
2) Call add_objects asynchronously: setTimeout( add_objects, 0, 20 );
http://codepen.io/anon/pen/bVbEEP

Three.js Raycasting with Camera as Origin

I'm trying to determine whether a point in space is visible to the camera or hidden behind other objects in the scene. I'm doing this by casting a ray from the position of the camera to that point in space and testing if that ray is intersected by an set of intersectable objects.
My problem is no intersections occur until the camera position itself intersects one of the objects in the set of intersectable objects.
I've created a jsfiddle in which, if an intersection is detected, a line is drawn from the camera position to the position in space i'm testing for visibility. Currently I believe, the line is only draw at specific points where the camera position intersects the set of intersectable objects.
How do I get the intersections to be registered as they should be, without having to have the camera position intersect objects in the set of intersectable objects?
the code:
var container;
var camera, controls, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
controls = new THREE.OrbitControls(camera);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [65, 83, 68];
controls.addEventListener('change', render);
// world
scene = new THREE.Scene();
var testObject_G = new THREE.CubeGeometry(100, 100, 5);
var testObject_M = new THREE.MeshBasicMaterial({
color: 0xBBBBBB
});
var testObject_Mesh = new THREE.Mesh(testObject_G, testObject_M);
testObject_Mesh.position.x = -150;
scene.add(testObject_Mesh);
var testObject_Mesh2 = new THREE.Mesh(testObject_G, testObject_M);
testObject_Mesh2.position.x = 0;
scene.add(testObject_Mesh2);
var testObject_Mesh3 = new THREE.Mesh(testObject_G, testObject_M);
testObject_Mesh3.position.x = 150;
scene.add(testObject_Mesh3);
scene2 = new THREE.Object3D();
// renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff, 1);
container = document.getElementById('container');
container.appendChild(renderer.domElement);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
controls.handleResize();
render();
}
function animate() {
requestAnimationFrame(animate);
controls.update();
}
function render() {
renderer.render(scene, camera);
castRays();
}
function castRays() {
// rays
var direction = new THREE.Vector3(0, 200, -200);
var startPoint = camera.position.clone();
var ray = new THREE.Raycaster(startPoint, direction);
scene.updateMatrixWorld(); // required, since you haven't rendered yet
var rayIntersects = ray.intersectObjects(scene.children, true);
if (rayIntersects[0]) {
console.log(rayIntersects[0]);
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(ray.ray.origin.x, ray.ray.origin.y, ray.ray.origin.z));
geometry.vertices.push(new THREE.Vector3(ray.ray.direction.x, ray.ray.direction.y, ray.ray.direction.z));
var line = new THREE.Line(geometry, material);
scene2.add( line );
}
scene.add(scene2);
}
Thank you
For anyone currently seeing this thread, THREE.Projector has been replaced.
Three.js THREE.Projector has been moved to
The code below handles a 3D vector. If you go to the link above, the first commenter provided the code for a 2D vector.
var vector = new THREE.Vector3();
var raycaster = new THREE.Raycaster();
var dir = new THREE.Vector3();
...
if ( camera instanceof THREE.OrthographicCamera ) {
vector.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, - 1 ); // z = - 1 important!
vector.unproject( camera );
dir.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
raycaster.set( vector, dir );
} else if ( camera instanceof THREE.PerspectiveCamera ) {
vector.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); // z = 0.5 important!
vector.unproject( camera );
raycaster.set( camera.position, vector.sub( camera.position ).normalize());
}
var intersects = raycaster.intersectObjects( objects, recursiveFlag );`
Your idea of casting a ray is good, however raycasting in three.js already does this :
mouse.x = ( ( event.clientX - renderer.domElement.offsetLeft ) / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( ( event.clientY - renderer.domElement.offsetTop ) / renderer.domElement.height ) * 2 + 1;
this formula maps a pixel coordinate from Screen Space to a point in Normalized Device Coordinate ( NDC ) Space.
projector.unprojectVector( vector, camera );
maps a point from NDC Space to a point in World space
Raycaster then creates a ray from the camera position through that world point.
Here is your working Fiddle in which I changed the way of raycasting in your scene and this works, all you have to do now is creating a ray with the right coordinates that I provided you.
r.68

Resources