2
votes

I have been struggling with issues concerning raycasting on small circlegeometries on a sphere.

I know raycasting can't be done with sprites and this is why I use circlegeometries, but it doesn't work all the time, and moreover the raycasting doesn't always work on circles but sometimes around them as well.

Does anybody have an idea ? Here is a JSBin to show you basically

Edit : I updated my previous version of JSBin, you can click any circleGeometries it will work here, run it with output tab only open for better results

This is related to the renderer width and height properties, my sphere isn't in fullscreen and this is why it fails.

Does anybody have an idea on how to set up it right in order to get this to work perfectly ?

2
Update to three.js r.65 and try it with sprites. See stackoverflow.com/questions/20823631/… - WestLangley
I updated my version to 65 but I didn't try sprites as it actually doesn't fit my needs, I don't wanna have sprites colliding with the sphere, just pastilles around it. Raycasting doesn't work better :/ - user3241019
Use a debugger so you can track your errors. objects appears to be empty. - WestLangley
Updated the JSBin, objects contains 2 elements. I don't get why raycasting fails, this code is simple. - user3241019
Your JSBin is using r.58... Sorry, I can't help you debug your code. But sep through it slowly with a debugger, and use the non-minified version of three.js r.66 -- three.js not three.min.js. You will figure out where things are going wrong. Good luck. - WestLangley

2 Answers

4
votes

The formula used to compute intersections wasn't the good one, here is the one that works :

    mouse.x = ( ( event.clientX - renderer.domElement.offsetLeft ) / renderer.domElement.width ) * 2 - 1;
    mouse.y = - ( ( event.clientY - renderer.domElement.offsetTop ) / renderer.domElement.height ) * 2 + 1;

mouse x and y have slightly changed from the examples you can get, and are now fine.

    var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);

    projector.unprojectVector(vector, camera);
    var ray = new THREE.Raycaster(camera.position, vector.sub(
            camera.position).normalize());

    var intersects = ray.intersectObjects(objects);

    if ( intersects.length > 0 ) {
    //do something
}
0
votes

if you looking for some thing like this....Your code might need little changes... check this link http://jsfiddle.net/ebeit303/rjJ6q/

// standard global variables
var container, scene, camera, renderer, controls, stats;
var clock = new THREE.Clock();

// custom global variables
var targetList = [];
var projector, mouse = { x: 0, y: 0 };

init();
animate();

// FUNCTIONS        
function init() 
{

    // SCENE
    scene = new THREE.Scene();
    // CAMERA
    var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
    var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 100000;
    camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
    scene.add(camera);
    camera.position.set(600,0,-1200);
    camera.lookAt(scene.position);  
    // RENDERER

        renderer = new THREE.CanvasRenderer(); 
    renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    container = document.getElementById( 'ThreeJS' );
    container.appendChild( renderer.domElement );
    // EVENTS

    // CONTROLS 

    // this material causes a mesh to use colors assigned to faces
    var faceColorMaterial = new THREE.MeshBasicMaterial( 
    { color: 0xffffff, vertexColors: THREE.FaceColors } );

    var sphereGeometry = new THREE.SphereGeometry( 500, 64, 64 );
    for ( var i = 0; i < sphereGeometry.faces.length; i++ ) 
    {
        face = sphereGeometry.faces[ i ];   
        face.color.setRGB( 0, 0, 0.8 * Math.random() + 0.2 );       
    }
    var sphere = new THREE.Mesh( sphereGeometry, faceColorMaterial );
    sphere.rotation.set(0, 14.5, 0);
    scene.add(sphere);

    //targetList.push(sphere);

    var j=0;

    for (var i =0; i<100;i+=5){
    //var circle = new THREE.CubeGeometry(5,5,5);
    var circle = new THREE.CircleGeometry(5, 8, 0, Math.PI * 2);
    //THREE.GeometryUtils.triangulateQuads(circle);
    var circleMaterial = new THREE.MeshBasicMaterial({color: 0xDEF2EF});
    circleMaterial.side = THREE.DoubleSide;

    var mesh = new THREE.Mesh(circle, circleMaterial);

    var Alon = i - 90;
    var Alat = j;

    var Aphi = Math.PI/2 - Alat * Math.PI / 180;
    var Atheta = 2 * Math.PI - Alon * Math.PI / 180;

    mesh.position.x = Math.sin(Aphi) * Math.cos(Atheta) * (501);
    mesh.position.y = Math.cos(Aphi) * (501);
    mesh.position.z = Math.sin(Aphi) * Math.sin(Atheta) * (501);    
    mesh.verticesNeedUpdate = true;
    mesh.lookAt( sphere.position );

    sphere.add(mesh);
    targetList.push(mesh);

    j++;
    }


    // initialize object to perform world/screen calculations
    projector = new THREE.Projector();

    // when the mouse moves, call the given function
    document.addEventListener( 'mousedown', onDocumentMouseDown, false );

}

function onDocumentMouseDown( event ) 
{


    // update the mouse variable
    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

    var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
    projector.unprojectVector( vector, camera );
    var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );

    var intersects = ray.intersectObjects( targetList );

    if ( intersects.length > 0 )
    {       

        intersects[ 0 ].object.material.color.setRGB( 0.8 * Math.random() + 0.2,
                                                     0.8 * Math.random() + 0.2,
                                                     0.8 * Math.random() + 0.2 );
    }

}


function animate() 
{

    requestAnimationFrame( animate );
    render();       
}


function render() 
{
    renderer.render( scene, camera );
}