PolosatiyVjih
PolosatiyVjih

Reputation: 279

Three.js 3D Zoom to mouse position

I have a next problem. I have a project made with Three.js + orbitControls.js for camera handling. There is a scene, with a simple cube on it, and the camera. I have a camera from orbitControls.js, when I do mouse wheel, it zoom in/out towards the center of the screen(default behaviour). I need to modify that, so that will be zooming in/out to mouse position on 3D object, like it is in 3D editors, like 3D Max, blender.

I do understand that logic should be something like that: take the position of mouse from where you are starting zooming, and actually where to you want to zoom in, store that value, zoom in and get the new mouse position, find offset between the first mouse position and current, and move camera to that offset during zooming in. But, it is not working ok. Mostly I think it is a probably the problem of coordinates of my camera, and the position where to I want to zoom in.

Here is my code:

 window.onload = function() {

        var renderer = new THREE.WebGLRenderer();
        var width = 640;
        var height = 480;
        renderer.setSize( width, height );
        var div = document.getElementById('canvas')
        div.appendChild( renderer.domElement );

        var scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera(
            70,
            width / height,
            0.1,
            10000
        );
        camera.position.set( 0, 10, 10 );
        camera.lookAt( scene.position );

        control = new THREE.OrbitControls( camera );

        var geometry = new THREE.CubeGeometry( 5, 5, 5 );
        var material = new THREE.MeshLambertMaterial( { color: 0xFF0000 } );
         mesh = new THREE.Mesh( geometry, material );
        scene.add( mesh );

        var light = new THREE.PointLight( 0xFFFF00 );
        light.position.set( 10, 0, 10 );
        scene.add( light );

        var dt = 30;
        var renderFunc = function() {
          update(dt);
          renderer.render(scene,camera);
        };

        setInterval(renderFunc,dt);

        //MY ZOOMING CODE.
        var mouseVector = new THREE.Vector3();
        var projector = new THREE.Projector();  
        var startMousePos = new THREE.Vector3();
        var intersectedPoint = new THREE.Vector3();
        var intersectedOffset = new THREE.Vector3();

//FIND INTERSECTED POSITION ON THE CUBE         
        canvas.onmousemove = function (event)
        {
            mouseVector.x = ( event.clientX / 640 ) * 2 - 1;
            mouseVector.y = - ( event.clientY / 480 ) * 2 + 1;
            startMousePos.x = mouseVector.x;
            startMousePos.y = mouseVector.y;

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

            var intersects = ray.intersectObjects( scene.children );

            if ( intersects.length > 0 )
            {
                 intersectedPoint = intersects[0].point;
            }
        }
//HERE I THINK I MUST TRANSLATE MY CAMERA.
        canvas.onmousewheel = function(event)
        {
            if(event.wheelDelta > 0)
            {
                camera.position.x -= intersectedPoint.x;
                camera.position.y -= intersectedPoint.y;
                camera.position.z -= intersectedPoint.z;
            }
            else
            {
                camera.position.x += intersectedPoint.x;
                camera.position.y += intersectedPoint.y;
                camera.position.z += intersectedPoint.z;

            }
        }
    };

Have somebody done that before? Could you please show me how did you solved that, or give me an advice how to handle that?

Thanks!

Upvotes: 7

Views: 8708

Answers (3)

Gangula
Gangula

Reputation: 7254

According to this Pull Request, this feature is going to be integrated into three.js in version r154 - scheduled to be released on June 28 2023 as of today.

This should also handle zooming using an orthographic camera which is mentioned in the following question

Upvotes: 1

Aasha joney
Aasha joney

Reputation: 546

Try this, it works

mousewheel = function (event) {
var factor = 15;
var mX = (event.clientX / jQuery(container).width()) * 2 - 1;
var mY = -(event.clientY / jQuery(container).height()) * 2 + 1;
var vector = new THREE.Vector3(mX, mY, 0.1);
vector.unproject(camera);
vector.sub(camera.position);
if (event.deltaY < 0) {
   camera.position.addVectors(camera.position, vector.setLength(factor));
   controls.target.addVectors(controls.target, vector.setLength(factor));
} else {
   camera.position.subVectors(camera.position, vector.setLength(factor));
   controls.target.subVectors(controls.target, vector.setLength(factor));
}
};

Upvotes: 2

Normal
Normal

Reputation: 547

After you get the intersect point, you can apply it as the orbitControl's target like this:

  if ( intersects.length > 0 )
        {
             intersectedPoint = intersects[0].point;
        }

 control.target = intersectedPoint ;

then, when you will zoom in it will be towards the point you chose.

Upvotes: 3

Related Questions