Question

I'm trying to rotate an object in three.js by dragging it with the mouse, so it has to rotate around the x and y axis. The code that I wrote works fine if I only try to rotate around one axis, but when I try to rotate around both, the rotation becomes weird, It always rotates around both axis even when the mouse is moving only in one direction:

function onDocumentMouseDown( event ) {
            document.addEventListener( 'mousemove', onDocumentMouseMove, false );

            //mouse point normalized to world coords
            lastPoint = {
                x : (event.clientX / windowHalfX)  * 2 - 1,
                y : -(event.clientY / windowHalfY)  * 2 + 1
            };

        }

        function onDocumentMouseMove( event ) {
            //new mouse position normalized to world coords
            newPoint = {
                x : (event.clientX / windowHalfX)  * 2 - 1,
                y : -(event.clientY / windowHalfY)  * 2 + 1
            };

            //rotation for both x and y axis
            rotationY = Math.atan(1 / (newPoint.x - lastPoint.x )) * (Math.PI / 180);
            rotationX = Math.atan(1 / (lastPoint.y - newPoint.y )) * (Math.PI / 180);   

            //apply rotation on Y axis
            quaternion.setFromAxisAngle( new THREE.Vector3(0,1,0).normalize(), rotationY); 
            cube.quaternion.multiplyQuaternions( quaternion, cube.quaternion ); 

            //aply rotation on X axis
            quaternion.setFromAxisAngle( new THREE.Vector3(1,0,0).normalize(), rotationX); 
            cube.quaternion.multiplyQuaternions( quaternion, cube.quaternion );

            //update last position to current one
            lastPoint = {
                x : newPoint.x,
                y : newPoint.y
            };
        }

I'm always applying rotation around both axis, but when the mouse moves in one direction, the rotation around the other axis should be 0 or near 0, but the rotation is very big and noticeable.

Can anyone point what I'm doing wrong?

Thanks

Was it helpful?

Solution

Your key word is "arc ball" control. the pseudocode below illustrate it

/**
 help function for arcball 
 orthogonal projection on sphere of radius 1, 
 standing in (x = 0, y = 0)
*/
inline vector3 ortho_project_on_sphere( float x , float y )
{
    vector3 p(x, y, 0);
    float ls = p.len_squared();
    if ( ls >= 1.0f )
        p.norm();
    else
        p.z = (float)sqrt(1.0f - ls);
    return p;
}
//-------------------------------------------------------------------------------
/*
  calculate rotation of arcball user input,
  used to perform object rotation by mouse.
  "from" and "to" the mouse on screen coordinates (with - x,y on screen) 
  in range of -1 to +1 
  the arcball radius is 1.0 and it stand in a center (x = 0, y = 0)
*/
inline xxquaternion arcball(const vector3& from, const vector3& to)
{
    vector3 p_f = ortho_project_on_sphere(from.x, from.y );
    vector3 p_t = ortho_project_on_sphere(to.x, to.y );
    vector3 c   = cross(p_f, p_t);
    float   d   = dot(p_f, p_t);
    return  xxquaternion(c.x, c.y, c.z, d);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top