【问题标题】:Rotate object around two world axis with quaternions使用四元数围绕两个世界轴旋转对象
【发布时间】:2014-04-18 13:21:00
【问题描述】:

我正在尝试通过用鼠标拖动来旋转three.js 中的对象,因此它必须围绕x 和y 轴旋转。如果我只尝试围绕一个轴旋转,我编写的代码可以正常工作,但是当我尝试围绕两个轴旋转时,旋转变得很奇怪,即使鼠标仅在一个方向上移动,它也总是围绕两个轴旋转:

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
            };
        }

我总是围绕两个轴应用旋转,但是当鼠标向一个方向移动时,围绕另一个轴的旋转应该是 0 或接近 0,但旋转非常大且很明显。

谁能指出我做错了什么?

谢谢

【问题讨论】:

    标签: rotation three.js quaternions


    【解决方案1】:

    您的关键词是“弧线球”控制。下面的伪代码说明了它

    /**
     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);
    }
    

    【讨论】:

    • 谢谢!做了一些关于轨迹球旋转的搜索,我也开始理解为什么将两个旋转组合起来不起作用:“旋转不像数字或方向那样组合 - 计算的顺序很重要。例如,向北走三英里,然后那么向东 2 英里将使您与向东走 2 英里然后向北 3 英里处于相同的位置。另一方面,俯仰 30 度然后偏航 20 度不会使您处于与偏航 20 度然后俯仰相同的方向三十度。”
    猜你喜欢
    • 2015-07-23
    • 1970-01-01
    • 2016-09-02
    • 2019-10-18
    • 2016-02-29
    • 2019-03-06
    • 1970-01-01
    • 2015-04-11
    相关资源
    最近更新 更多