Manu
Manu

Reputation: 36

Three.js StereoEffect displays meshes across 2 eyes

I have a THREE.js scene using StereoEffect renderer. However, when I add new meshes to the scene, they are displayed across the two eyes instead of being duplicated for each eye. I believe THREE.js is supposed to do it automatically and I don't have to duplicate them myself ? (I tried duplicating them but it is a lot of annoying calculation and I could not manage it)

My meshes are actually transparent planes, and I add a DOM element on the top of them to have a flat display.

Illustrating Example

Upvotes: 0

Views: 378

Answers (1)

Manu
Manu

Reputation: 36

OK I finally found it ! I tried putting back on a texture (not invisible) on my meshes and I discovered the problem.

When we use StereoEffect and we see that our mesh is duplicated on both views, it is actually an illusion : THREE.JS puts an image there, but the actual object is invisible, put exactly at the middle of the two images ! See image here : explanation

If you use raycaster for instance, it will tell you there's not an instersection where you see the mesh, but at the center of the line from left image to right image ! Same for mesh.position.

So what I did was keep an invisible texture, and create two div tags that I placed symmetrically around the mesh position :

var middleX = window.offsetWidth/2;
//left div
if(this.element.id.indexOf("-2") == -1){
    var posL = coords2d.x - middleX/2;
    this.element.style.left = posL + 'px';
    //Hide if gets on the right part of the screen
    if(posL > middleX) this.element.style.display = 'none';
}
//right div
else{
    var posR = coords2d.x + middleX/2;
    this.element.style.left = posR + 'px';
    //Hide if gets on the left part of the screen
    if(posR < middleX) this.element.style.display = 'none';
}                    

That gives the illusion that my mesh is there, put it is just empty divs.

Then, to check if someone clicks on my mesh, I do the opposite : I go back to the real position of the mesh before sending it to raycaster !

function hasClicked(e) {
        e.preventDefault();
        var clientX,clientY;

        //GET REAL POSITION OF OBJECT
        var middleX = window.offsetWidth/2;
        //Right screen
        if(e.clientX>middleX){
            clientX = e.clientX - middleX/2;
        }
        //Left screen
        else {
            clientX = e.clientX + middleX/2;
        } 
        clientY = e.clientY;  //Keep same Y coordinate

        //TRANSFORM THESE COORDS ON SCREEN INTO THREE.JS COORDS
        var mouse = new THREE.Vector2();
        mouse.x = (clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(clientY / window.innerHeight) * 2 + 1;

        //USE RAYCASTER
        raycaster.setFromCamera(mouse, camera);

        var intersects = raycaster.intersectObjects(arrowManager.storage);

        if (intersects.length > 0) {
            //It works !!!
        }
    }

And it works perfectly fine !! Hope this can help someone else, I was getting really desperate here ;)

Upvotes: 1

Related Questions