Question

When rotating an Object, I think there are two ways[focus on rotate the object, not use camera]:

1.rotate the object directly in render(), just like(canvas_geometry_cube.html)

  cube.rotation.y += ( targetRotationY - cube.rotation.y ) * 0.05;
  cube.rotation.x += ( targetRotationY - cube.rotation.x ) * 0.05;

However, here has a problem, when you rotate in some angle, it not works. with the code:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js canvas - geometry - cube</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #f0f0f0;
                margin: 0px;
                overflow: hidden;
            }
        </style>
    </head>
    <body>

        <script src="../build/three.min.js"></script>

        <script src="js/libs/stats.min.js"></script>

        <script>

            var container, stats;

            var camera, scene, renderer;

            var cube, plane;

            var targetRotationX = 0;
            var targetRotationOnMouseDownX = 0;

            var targetRotationY = 0;
            var targetRotationOnMouseDownY = 0;

            var mouseX = 0;
            var mouseXOnMouseDown = 0;

            var mouseY = 0;
            var mouseYOnMouseDown = 0;

            var windowHalfX = window.innerWidth / 2;
            var windowHalfY = window.innerHeight / 2;

            init();
            animate();

            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                var info = document.createElement( 'div' );
                info.style.position = 'absolute';
                info.style.top = '10px';
                info.style.width = '100%';
                info.style.textAlign = 'center';
                info.innerHTML = 'Drag to spin the cube';
                container.appendChild( info );

                camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
                camera.position.y = 150;
                camera.position.z = 500;

                scene = new THREE.Scene();

                // Cube

                var geometry = new THREE.CubeGeometry( 200, 200, 200 );

                for ( var i = 0; i < geometry.faces.length; i += 2 ) {

                    var hex = Math.random() * 0xffffff;
                    geometry.faces[ i ].color.setHex( hex );
                    geometry.faces[ i + 1 ].color.setHex( hex );

                }

                var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );

                cube = new THREE.Mesh( geometry, material );
                cube.position.y = 150;
                scene.add( cube );

                // Plane

                var geometry = new THREE.PlaneGeometry( 200, 200 );
                geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );

                var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );

                plane = new THREE.Mesh( geometry, material );
                scene.add( plane );

                renderer = new THREE.CanvasRenderer();
                renderer.setClearColor( 0xf0f0f0 );
                renderer.setSize( window.innerWidth, window.innerHeight );

                container.appendChild( renderer.domElement );

                stats = new Stats();
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.top = '0px';
                container.appendChild( stats.domElement );

                document.addEventListener( 'mousedown', onDocumentMouseDown, false );
                document.addEventListener( 'touchstart', onDocumentTouchStart, false );
                document.addEventListener( 'touchmove', onDocumentTouchMove, false );

                //

                window.addEventListener( 'resize', onWindowResize, false );

            }

            function onWindowResize() {

                windowHalfX = window.innerWidth / 2;
                windowHalfY = window.innerHeight / 2;

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }

            //

            function onDocumentMouseDown( event ) {

                event.preventDefault();

                document.addEventListener( 'mousemove', onDocumentMouseMove, false );
                document.addEventListener( 'mouseup', onDocumentMouseUp, false );
                document.addEventListener( 'mouseout', onDocumentMouseOut, false );

                mouseXOnMouseDown = event.clientX - windowHalfX;
                targetRotationOnMouseDownX = targetRotationX;
                mouseYOnMouseDown = event.clientY - windowHalfY;
                targetRotationOnMouseDownY = targetRotationY;
            }

            function onDocumentMouseMove( event ) {

                mouseX = event.clientX - windowHalfX;
                targetRotationX = targetRotationOnMouseDownX + ( mouseX - mouseXOnMouseDown ) * 0.02;

                mouseY = event.clientY - windowHalfY;
                targetRotationY = targetRotationOnMouseDownY + ( mouseY - mouseYOnMouseDown ) * 0.02;
            }

            function onDocumentMouseUp( event ) {

                document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
                document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
                document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

            }

            function onDocumentMouseOut( event ) {

                document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
                document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
                document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

            }

            function onDocumentTouchStart( event ) {

                if ( event.touches.length === 1 ) {

                    event.preventDefault();

                    mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
                    targetRotationOnMouseDownX = targetRotationX;
                    mouseYOnMouseDown = event.touches[ 0 ].pageY - windowHalfY;
                    targetRotationOnMouseDownY = targetRotationY;
                }

            }

            function onDocumentTouchMove( event ) {

                if ( event.touches.length === 1 ) {

                    event.preventDefault();

                    mouseX = event.touches[ 0 ].pageX - windowHalfX;
                    targetRotationX = targetRotationOnMouseDownX + ( mouseX - mouseXOnMouseDown ) * 0.05;
                    mouseY = event.touches[ 0 ].pageY - windowHalfY;
                    targetRotationY = targetRotationOnMouseDownY + ( mouseY - mouseYOnMouseDown ) * 0.05;
                }

            }

            //

            function animate() {

                requestAnimationFrame( animate );

                render();
                stats.update();

            }

            function render() {

                cube.rotation.x += ( targetRotationY - cube.rotation.x ) * 0.05;
                cube.rotation.y += ( targetRotationX - cube.rotation.y ) * 0.05;
                renderer.render( scene, camera );

            }

        </script>

    </body>
</html>

2.So I try another way, to save the rotation Matrix about the mouse move(refer to the links in https://github.com/mrdoob/three.js/issues/1230).
var newRotationMatrix = new THREE.Matrix4();

   newRotationMatrix.identity();
   var axisy =  new THREE.Vector3(0,1,0);
   var axisx =  new THREE.Vector3(1,0,0);
   var deltaX = newX - lastMouseX;
   newRotationMatrix.makeRotationAxis(axisy.normalize(), THREE.Math.degToRad(deltaX / 10));
   rotationMatrix.multiply(newRotationMatrix);

   var deltaY = newY - lastMouseY;
   newRotationMatrix.makeRotationAxis(axisx.normalize(), THREE.Math.degToRad(deltaY / 10));
   rotationMatrix.multiply(newRotationMatrix);

and when in the render() I use: cube.rotation.setRotationFromMatrix(rotationMatrix); But it does not work. Can you help me, thank you!

With the whole code:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js canvas - geometry - cube</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #f0f0f0;
                margin: 0px;
                overflow: hidden;
            }
        </style>
    </head>
    <body>

        <script src="../build/three.min.js"></script>

        <script src="js/libs/stats.min.js"></script>

        <script>

            var container, stats;

            var camera, scene, renderer;

            var cube, plane;

            var windowHalfX = window.innerWidth / 2;
            var windowHalfY = window.innerHeight / 2;

            init();
            animate();
            var mouseDown = false;
            var lastMouseX = null;
            var lastMouseY = null;

            var rotationMatrix = new THREE.Matrix4();
            rotationMatrix.identity();
            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                var info = document.createElement( 'div' );
                info.style.position = 'absolute';
                info.style.top = '10px';
                info.style.width = '100%';
                info.style.textAlign = 'center';
                info.innerHTML = 'Drag to spin the cube';
                container.appendChild( info );

                camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
                camera.position.y = 150;
                camera.position.z = 500;

                scene = new THREE.Scene();

                // Cube

                var geometry = new THREE.CubeGeometry( 200, 200, 200 );

                for ( var i = 0; i < geometry.faces.length; i += 2 ) {

                    var hex = Math.random() * 0xffffff;
                    geometry.faces[ i ].color.setHex( hex );
                    geometry.faces[ i + 1 ].color.setHex( hex );

                }

                var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );

                cube = new THREE.Mesh( geometry, material );
                cube.position.y = 150;
                scene.add( cube );

                // Plane

                var geometry = new THREE.PlaneGeometry( 800, 800 );
                geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );

                var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );

                plane = new THREE.Mesh( geometry, material );
                plane.position.y = -150;
                scene.add( plane );

                renderer = new THREE.WebGLRenderer();
                //renderer.setClearColor( 0xf0f0f0 );
                renderer.setSize( window.innerWidth, window.innerHeight );

                container.appendChild( renderer.domElement );

                stats = new Stats();
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.top = '0px';
                container.appendChild( stats.domElement );

                document.addEventListener( 'mousedown', onDocumentMouseDown, false );
                document.addEventListener( 'mousemove', onDocumentMouseMove, false );
                document.addEventListener( 'mouseup', onDocumentMouseUp, false );
                //

                window.addEventListener( 'resize', onWindowResize, false );

            }

            function onWindowResize() {

                windowHalfX = window.innerWidth / 2;
                windowHalfY = window.innerHeight / 2;

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }

            function onDocumentMouseUp(event) {
                mouseDown = false;
            }


            function onDocumentMouseDown( event ) {

                mouseDown = true;
                lastMouseX = event.clientX;
                lastMouseY = event.clientY;
            }

            function onDocumentMouseMove( event ) {
                if(!mouseDown)
                {
                    return;
                }
                var newX = event.clientX;
                var newY = event.clientY;

                var newRotationMatrix = new THREE.Matrix4();

                newRotationMatrix.identity();
                var axisy =  new THREE.Vector3(0,1,0);
                var axisx =  new THREE.Vector3(1,0,0);
                var deltaX = newX - lastMouseX;
                newRotationMatrix.makeRotationAxis(axisy.normalize(), THREE.Math.degToRad(deltaX / 10));
                rotationMatrix.multiply(newRotationMatrix);

                var deltaY = newY - lastMouseY;
                newRotationMatrix.makeRotationAxis(axisx.normalize(), THREE.Math.degToRad(deltaY / 10));
                rotationMatrix.multiply(newRotationMatrix);

                lastMouseX = newX;
                lastMouseY = newY;
            }

            //

            function animate() {

                requestAnimationFrame( animate );

                render();
                stats.update();

            }

            function render() {
                 cube.rotation.setRotationFromMatrix(rotationMatrix);
                renderer.render( scene, camera );

            }

        </script>

    </body>
</html>

Rotation solved

Sorry for my poor english. Object could set rotation from quaternion. So First I get the quaternion from the mouse move.(trackball modify from the control trackball) And then apply to the object.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>three.js canvas - geometry - cube</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            font-family: Monospace;
            background-color: #f0f0f0;
            margin: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>

<script src="../build/three.min.js"></script>

<script src="js/libs/stats.min.js"></script>

<script>

var container, stats;

var camera, scene, renderer;

var cube, plane;



var mouseDown = false;
var rotateStartP = new THREE.Vector3(0,0,1);
var rotateEndP = new THREE.Vector3(0,0,1);

var lastPosX;
var lastPosY;
var targetRotationY = 0;
var targetRotationX = 0;
var quater;
//var rotateQuaternion = new THREE.Quaternion();
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

init();
animate();

function init() {

    container = document.createElement( 'div' );
    document.body.appendChild( container );

    var info = document.createElement( 'div' );
    info.style.position = 'absolute';
    info.style.top = '10px';
    info.style.width = '100%';
    info.style.textAlign = 'center';
    info.innerHTML = 'Drag to spin the cube';
    container.appendChild( info );

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.y = 150;
    camera.position.z = 500;

    scene = new THREE.Scene();

    // Cube

    var geometry = new THREE.CubeGeometry( 200, 200, 200 );

    for ( var i = 0; i < geometry.faces.length; i += 2 ) {

        var hex = Math.random() * 0xffffff;
        geometry.faces[ i ].color.setHex( hex );
        geometry.faces[ i + 1 ].color.setHex( hex );

    }

    var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );

    cube = new THREE.Mesh( geometry, material );
    cube.position.y = 150;
    scene.add( cube );

    // Plane

    var geometry = new THREE.PlaneGeometry( 200, 200 );
    geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );

    var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );

    plane = new THREE.Mesh( geometry, material );
    scene.add( plane );

    renderer = new THREE.CanvasRenderer();
    renderer.setClearColor( 0xf0f0f0 );
    renderer.setSize( window.innerWidth, window.innerHeight );

    container.appendChild( renderer.domElement );

    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.top = '0px';
    container.appendChild( stats.domElement );

    document.addEventListener( 'mousedown', onDocumentMouseDown, false );
    document.addEventListener( 'touchstart', onDocumentTouchStart, false );
    document.addEventListener( 'touchmove', onDocumentTouchMove, false );

    //

    window.addEventListener( 'resize', onWindowResize, false );

}

function onWindowResize() {

    windowHalfX = window.innerWidth / 2;
    windowHalfY = window.innerHeight / 2;

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

}

//

function onDocumentMouseDown( event ) {

    event.preventDefault();

    document.addEventListener( 'mousemove', onDocumentMouseMove, false );
    document.addEventListener( 'mouseup', onDocumentMouseUp, false );
    document.addEventListener( 'mouseout', onDocumentMouseOut, false );
    mouseDown = true;
    rotateStartP = projectOnTrackball(event.clientX, event.clientY);
}

function onDocumentMouseMove( event ) {

    if(!mouseDown)
    {
        return;
    }

    rotateEndP = projectOnTrackball(event.clientX, event.clientY);


}
function getMouseOnScreen( pageX, pageY) {

    return new THREE.Vector2.set(pageX / window.innerWidth ,pageY / window.innerHeight);

}

function projectOnTrackball(pageX, pageY) // The screen coordinate[(0,0)on the left-top] convert to the
    //trackball coordinate [(0,0) on the center of the page]
{
    var mouseOnBall = new THREE.Vector3();
    mouseOnBall.set(
                    ( pageX - window.innerWidth * 0.5 ) / (window.innerWidth * .5),
                    ( window.innerHeight * 0.5 - pageY ) / ( window.innerHeight * .5),
            0.0
    );

    var length = mouseOnBall.length();
    if (length > 1.0) {

        mouseOnBall.normalize();

    }
    else {
        mouseOnBall.z = Math.sqrt(1.0 - length * length);
    }
    return mouseOnBall;
}

function rotateMatrix(rotateStart, rotateEnd)
{
    var axis = new THREE.Vector3(),
            quaternion = new THREE.Quaternion();

    var angle = Math.acos( rotateStart.dot( rotateEnd ) / rotateStart.length() / rotateEnd.length() );

    if ( angle )
    {
        axis.crossVectors( rotateStart, rotateEnd ).normalize();
        angle *= 0.01;            //Here we could define rotate speed
        quaternion.setFromAxisAngle( axis, angle );
    }
    return  quaternion;
}

function onDocumentMouseUp( event ) {

    document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
    document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
    document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
    mouseDown = false;
    rotateStartP = rotateEndP;

}

function onDocumentMouseOut( event ) {

    document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
    document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
    document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

}

function onDocumentTouchStart( event ) {

    if ( event.touches.length === 1 ) {

        event.preventDefault();
        /*
         mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
         targetRotationOnMouseDownX = targetRotationX;
         mouseYOnMouseDown = event.touches[ 0 ].pageY - windowHalfY;
         targetRotationOnMouseDownY = targetRotationY;  */
    }

}

function onDocumentTouchMove( event ) {

    if ( event.touches.length === 1 ) {

        event.preventDefault();
        /*
         mouseX = event.touches[ 0 ].pageX - windowHalfX;
         targetRotationX = targetRotationOnMouseDownX + ( mouseX - mouseXOnMouseDown ) * 0.05;
         mouseY = event.touches[ 0 ].pageY - windowHalfY;
         targetRotationY = targetRotationOnMouseDownY + ( mouseY - mouseYOnMouseDown ) * 0.05; */
    }

}

//
function animate() {

    requestAnimationFrame( animate );
    render();
    stats.update();

}

function render() {
    //if(rotateStartP != rotateEndP) {
        //rotateQuaternion = rotateMatrix(rotateStartP, rotateEndP);
        //quater=cube.quaternion;
        //quater.multiplyQuaternions(rotateQuaternion, quater);
        //quater.multiply(rotateQuaternion);
        //quater.normalize();
        var rotateQuaternion = rotateMatrix(rotateStartP, rotateEndP);
        quater=cube.quaternion;
        quater.multiplyQuaternions(rotateQuaternion,quater);
        quater.normalize();
        cube.setRotationFromQuaternion(quater);
   // }


    renderer.render( scene, camera );

}

</script>

</body>
</html>
Was it helpful?

Solution 2

Add the answer, so that, it would help for the other people who has the similar problem

<!DOCTYPE html>
<html lang="en">
<head>
    <title>three.js canvas - geometry - cube</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            font-family: Monospace;
            background-color: #f0f0f0;
            margin: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>

<script src="../build/three.min.js"></script>

<script src="js/libs/stats.min.js"></script>

<script>

var container, stats;

var camera, scene, renderer;

var cube, plane;



var mouseDown = false;
var rotateStartP = new THREE.Vector3(0,0,1);
var rotateEndP = new THREE.Vector3(0,0,1);

var lastPosX;
var lastPosY;
var targetRotationY = 0;
var targetRotationX = 0;
var quater;
//var rotateQuaternion = new THREE.Quaternion();
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

init();
animate();

function init() {

    container = document.createElement( 'div' );
    document.body.appendChild( container );

    var info = document.createElement( 'div' );
    info.style.position = 'absolute';
    info.style.top = '10px';
    info.style.width = '100%';
    info.style.textAlign = 'center';
    info.innerHTML = 'Drag to spin the cube';
    container.appendChild( info );

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.y = 150;
    camera.position.z = 500;

    scene = new THREE.Scene();

    // Cube

    var geometry = new THREE.CubeGeometry( 200, 200, 200 );

    for ( var i = 0; i < geometry.faces.length; i += 2 ) {

        var hex = Math.random() * 0xffffff;
        geometry.faces[ i ].color.setHex( hex );
        geometry.faces[ i + 1 ].color.setHex( hex );

    }

    var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );

    cube = new THREE.Mesh( geometry, material );
    cube.position.y = 150;
    scene.add( cube );

    // Plane

    var geometry = new THREE.PlaneGeometry( 200, 200 );
    geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );

    var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );

    plane = new THREE.Mesh( geometry, material );
    scene.add( plane );

    renderer = new THREE.CanvasRenderer();
    renderer.setClearColor( 0xf0f0f0 );
    renderer.setSize( window.innerWidth, window.innerHeight );

    container.appendChild( renderer.domElement );

    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.top = '0px';
    container.appendChild( stats.domElement );

    document.addEventListener( 'mousedown', onDocumentMouseDown, false );
    document.addEventListener( 'touchstart', onDocumentTouchStart, false );
    document.addEventListener( 'touchmove', onDocumentTouchMove, false );

    //

    window.addEventListener( 'resize', onWindowResize, false );

}

function onWindowResize() {

    windowHalfX = window.innerWidth / 2;
    windowHalfY = window.innerHeight / 2;

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

}

//

function onDocumentMouseDown( event ) {

    event.preventDefault();

    document.addEventListener( 'mousemove', onDocumentMouseMove, false );
    document.addEventListener( 'mouseup', onDocumentMouseUp, false );
    document.addEventListener( 'mouseout', onDocumentMouseOut, false );
    mouseDown = true;
    rotateStartP = projectOnTrackball(event.clientX, event.clientY);
}

function onDocumentMouseMove( event ) {

    if(!mouseDown)
    {
        return;
    }

    rotateEndP = projectOnTrackball(event.clientX, event.clientY);


}
function getMouseOnScreen( pageX, pageY) {

    return new THREE.Vector2.set(pageX / window.innerWidth ,pageY / window.innerHeight);

}

function projectOnTrackball(pageX, pageY) // The screen coordinate[(0,0)on the left-top] convert to the
    //trackball coordinate [(0,0) on the center of the page]
{
    var mouseOnBall = new THREE.Vector3();
    mouseOnBall.set(
                    ( pageX - window.innerWidth * 0.5 ) / (window.innerWidth * .5),
                    ( window.innerHeight * 0.5 - pageY ) / ( window.innerHeight * .5),
            0.0
    );

    var length = mouseOnBall.length();
    if (length > 1.0) {

        mouseOnBall.normalize();

    }
    else {
        mouseOnBall.z = Math.sqrt(1.0 - length * length);
    }
    return mouseOnBall;
}

function rotateMatrix(rotateStart, rotateEnd)
{
    var axis = new THREE.Vector3(),
            quaternion = new THREE.Quaternion();

    var angle = Math.acos( rotateStart.dot( rotateEnd ) / rotateStart.length() / rotateEnd.length() );

    if ( angle )
    {
        axis.crossVectors( rotateStart, rotateEnd ).normalize();
        angle *= 0.01;            //Here we could define rotate speed
        quaternion.setFromAxisAngle( axis, angle );
    }
    return  quaternion;
}

function onDocumentMouseUp( event ) {

    document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
    document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
    document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
    mouseDown = false;
    rotateStartP = rotateEndP;

}

function onDocumentMouseOut( event ) {

    document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
    document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
    document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

}

function onDocumentTouchStart( event ) {

    if ( event.touches.length === 1 ) {

        event.preventDefault();
        /*
         mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
         targetRotationOnMouseDownX = targetRotationX;
         mouseYOnMouseDown = event.touches[ 0 ].pageY - windowHalfY;
         targetRotationOnMouseDownY = targetRotationY;  */
    }

}

function onDocumentTouchMove( event ) {

    if ( event.touches.length === 1 ) {

        event.preventDefault();
        /*
         mouseX = event.touches[ 0 ].pageX - windowHalfX;
         targetRotationX = targetRotationOnMouseDownX + ( mouseX - mouseXOnMouseDown ) * 0.05;
         mouseY = event.touches[ 0 ].pageY - windowHalfY;
         targetRotationY = targetRotationOnMouseDownY + ( mouseY - mouseYOnMouseDown ) * 0.05; */
    }

}

//
function animate() {

    requestAnimationFrame( animate );
    render();
    stats.update();

}

function render() {
    //if(rotateStartP != rotateEndP) {
        //rotateQuaternion = rotateMatrix(rotateStartP, rotateEndP);
        //quater=cube.quaternion;
        //quater.multiplyQuaternions(rotateQuaternion, quater);
        //quater.multiply(rotateQuaternion);
        //quater.normalize();
        var rotateQuaternion = rotateMatrix(rotateStartP, rotateEndP);
        quater=cube.quaternion;
        quater.multiplyQuaternions(rotateQuaternion,quater);
        quater.normalize();
        cube.setRotationFromQuaternion(quater);
   // }


    renderer.render( scene, camera );

}

</script>

</body>
</html>

OTHER TIPS

I've taken the code from @yongnan and modified it to work as I would have expected the cube to rotate while dragging. You can download the code here: https://github.com/defmech/Three.js-Object-Rotation-with-Quaternion

Example here: http://projects.defmech.com/ThreeJSObjectRotationWithQuaternion/

I realise this is an old post - but for people happening on it & just in case anyone is interested: I've put together a first version of a drag controller which enables drag rotation about 3 axes, with the axis of rotation specified by the mouse pointer rather than the center of the object.

It works with touch, and should behave the same irrespective of camera position/object position. I've also had it working alongside OrbitControls.js, so that the whole scene rotates/translates if blank canvas is clicked on.

You can read more about it and get the code here: https://virtual.blue/point-drag-controls

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top