如何在three.js中旋转对象(r66)不使用控制相机的轨迹球

时间:2014-04-22 15:10:07

标签: rotation three.js trackball

旋转物体时,我认为有两种方法[专注于旋转物体,而不是使用相机]:

1.直接在render()中旋转对象,就像(canvas_geometry_cube.html)

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

然而,这里有一个问题,当你以某个角度旋转时,它不起作用。 代码:

<!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.所以我尝试另一种方法,保存关于鼠标移动的旋转矩阵(参考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);

当我在render()中使用时:      cube.rotation.setRotationFromMatrix(rotationMatrix); 但它不起作用。 你能帮助我吗,谢谢你!

使用整个代码:

<!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>

旋转解决了

抱歉我的英语不好。 对象可以从四元数设置旋转。首先,我从鼠标移动中获得四元数。(轨迹球从控制轨迹球修改)然后应用于对象。

<!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>

3 个答案:

答案 0 :(得分:3)

我从@yongnan那里获取代码并将其修改为工作,因为我希望在拖动时旋转立方体。您可以在此处下载代码:https://github.com/defmech/Three.js-Object-Rotation-with-Quaternion

此处示例:http://projects.defmech.com/ThreeJSObjectRotationWithQuaternion/

答案 1 :(得分:1)

添加答案,这对其他有类似问题的人有帮助

<!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>

答案 2 :(得分:0)

我意识到这是一个古老的帖子 - 但对于那些发生在其上的人而言以防任何人感兴趣:我已经将第一个版本的拖动控制器放在一起,它允许拖动旋转大约3个轴,旋转轴由鼠标指针而不是对象的中心指定。

它适用于触摸,无论相机位置/物体位置如何,都应该表现相同。我还让它与OrbitControls.js一起工作,这样如果点击空白画布,整个场景就会旋转/翻译。

您可以阅读更多相关信息并在此处获取代码:https://virtual.blue/point-drag-controls