Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Threejs raycaster only works super close

Tags:

three.js

I was following mrdoobs examples of how to use raycasting to handle clickable objects. I have also looked at all of the many many similar questions and have tried countless things. The raycasting works... If I am at a distance of less than 1.

The Raycaster is set to near 0 and far infinity though (defaults). I haven't seen any code examples where distance was set.

I am hoping for another pair of eyes.

// snippet
glow.clickables = [];
var cubeGeo = new THREE.CubeGeometry(2, 2, 2);
cubeGeo.computeFaceNormals();
var cube = new THREE.Mesh(cubeGeo, redmat);
cube.position.y = 10;
cube.position.x = 0;
cube.position.z = -12;
cube.overdraw = true;
glow.Vis.scene.add(cube);
glow.clickables.push(cube);
onclick_();

var onclick_ = function() {
    $('#world').on('mousedown', function(e){
        var mouseX = (event.offsetX / $('#world').width()) * 2 - 1;
        var mouseY =  - ( event.offsetY / $('#world').height()) * 2 + 1;
        var vector = new THREE.Vector3(mouseX, mouseY,  0.1); //what should z be set to?
        //console.info(vector); // A vector between -1,1 for both x and y. Z is whatever is set on the line above
        projector.unprojectVector(vector, glow.Vis.camera);
        var conts = glow.Vis.controls.getObject().position; // control 3dObject which the camera is added to.
        var clickRay = new THREE.Raycaster(conts, vector.sub(conts).normalize());
        var intersects = clickRay.intersectObjects(glow.clickables);
        console.info(intersects.length);
        if(intersects.length > 0) {
            alert("Click detected!");
        }
    });
}
like image 224
Matt Gardner Avatar asked Jul 28 '13 08:07

Matt Gardner


2 Answers

For mouse detecting (far or near! no matter!), do this:

put this in your global:

var pointerDetectRay, projector, mouse2D;  

put this in your init() function:

pointerDetectRay = new THREE.Raycaster();
pointerDetectRay.ray.direction.set(0, -1, 0);
projector = new THREE.Projector();
mouse2D = new THREE.Vector3(0, 0, 0);

put this in your render() loop function:

pointerDetectRay = projector.pickingRay(mouse2D.clone(), camera);

and it's your mouse event:

function onDocumentMouseMove(event) {
    event.preventDefault();
    mouse2D.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
}

Now, every where that you want to detect the objects under your mouse pointer, use this:

var intersects = pointerDetectRay.intersectObjects(scene.children);
if (intersects.length > 0) {
    var intersect = intersects[0];
    // intersect is the object under your mouse!
    // do what ever you want!
}
like image 45
MeTe-30 Avatar answered Sep 28 '22 07:09

MeTe-30


Setting the mouse position this way is more accurate.

        var rect = renderer.domElement.getBoundingClientRect();
        mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
        mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;
like image 133
Doguleez Avatar answered Sep 28 '22 07:09

Doguleez