简体   繁体   English

THREE.js:需要帮助旋转四元数

[英]THREE.js: Need Help rotating with Quaternions

I'm looking to understand quaternions for three.js, but for all the tutorials, I haven't been able to translate them into the application I need. 我想要了解three.js的四元数,但是对于所有教程,我都无法将它们转换为我需要的应用程序。 This is the problem: 这就是问题:

Given a sphere centered at (0,0,0), I want to angle an object on the sphere's surface, that acts as the focal point for the camera. 给定一个以(0,0,0)为中心的球体,我想在球体表面上对一个物体进行角度,该物体充当相机的焦点。 This point is to be moved and rotated on the surface with keyboard input. 使用键盘输入在曲面上移动和旋转此点。 Setting the focal point into a chosen orbit is easy of course, but maintaining the right rotation perpendicular to the surface escapes me. 将焦点设置到选定的轨道当然很容易,但是保持垂直于表面的正确旋转逃离了我。 I know quaternions are neccessary for smooth movement and arbitrary axis rotation, but I don't know where to start. 我知道四元数是平滑运动和任意轴旋转的必要条件,但我不知道从哪里开始。

The second part then is rotating the camera offset with the focal point. 然后第二部分用焦点旋转相机偏移。 The snippet I found for this does not have the desired effect anymore, as the cameraOffset does not inherit the rotation: 我找到的片段不再具有所需的效果,因为cameraOffset不继承旋转:

var cameraOffset = relativeCameraOffset.clone().applyMatrix4( focalPoint.matrixWorld );
camera.position.copy( focalPoint.position.clone().add(cameraOffset) );
camera.lookAt( focalPoint.position );

Update 1: Tried it with fixed camera on the pole and rotating the planet. 更新1:在杆上使用固定摄像头尝试并旋转行星。 But unless I'm missing something important, this fails as well, due to the directions getting skewed completely when going towards the equator. 但除非我遗漏了一些重要的东西,否则这也会失败,因为朝向赤道的方向完全倾斜。 (Left becomes forward). (左边变成前锋)。 Code in update is: 更新中的代码是:

        acceleration.set(0,0,0);

        if (keyboard.pressed("w")) acceleration.x = 1 * accelerationSpeed;
        if (keyboard.pressed("s")) acceleration.x = -1 * accelerationSpeed;
        if (keyboard.pressed("a")) acceleration.z = 1 * accelerationSpeed;
        if (keyboard.pressed("d")) acceleration.z = -1 * accelerationSpeed;
        if (keyboard.pressed("q")) acceleration.y = 1 * accelerationSpeed;
        if (keyboard.pressed("e")) acceleration.y = -1 * accelerationSpeed;

        velocity.add(acceleration);
        velocity.multiplyScalar(dropOff);
        velocity.max(minV);
        velocity.min(maxV);

        planet.mesh.rotation.x += velocity.x;
        planet.mesh.rotation.y += velocity.y;
        planet.mesh.rotation.z += velocity.z;

So I'm still open for suggestions. 所以我仍然愿意接受建议。

Finally found the solution from a mixture of matrices and quaternions: 最后从矩阵和四元数的混合物中找到了解决方案:

    //Setup
    var ux = new THREE.Vector3(1,0,0);
    var uy = new THREE.Vector3(0,1,0);
    var uz = new THREE.Vector3(0,0,1);

    var direction = ux.clone();
    var m4 = new THREE.Matrix4();
    var dq = new THREE.Quaternion(); //direction quad base
    var dqq;   //final direction quad
    var dq2 = new THREE.Quaternion();
    dq2.setFromAxisAngle(uz,Math.PI/2); //direction perpendicular rot

        //Update
        if (velocity.length() < 0.1) return;
        if (velocity.x) { focalPoint.translateY( velocity.x ); }
        if (velocity.y) { focalPoint.translateX( velocity.y ); }
        //create new direction from focalPoint quat, but perpendicular
        dqq = dq.clone().multiply(focalPoint.quaternion).multiply(dq2);

        velocity.multiplyScalar(dropOff);
        //forward direction vector          
        direction = ux.clone().applyQuaternion(dqq).normalize();
        //use Matrix4.lookAt to align focalPoint with the direction
        m4.lookAt(focalPoint.position, planet.mesh.position, direction);
        focalPoint.quaternion.setFromRotationMatrix(m4);

        var cameraOffset = relativeCameraOffset.clone();
        cameraOffset.z = cameraDistance;

        cameraOffset.applyQuaternion(focalPoint.quaternion);

        camera.position = focalPoint.position.clone().add(cameraOffset) ;
        //use direction for camera rotation as well
        camera.up = direction;
        camera.lookAt( focalPoint.position );

This is the hard core of it. 这是它的核心。 It pans (and with some extension rotates) around the planet without the poles being an issue. 它在行星周围平移(并且有一些延伸旋转)而没有杆是一个问题。

I'm not sure to understand your problem. 我不太明白你的问题。 But for help, I draw a boat on a sphere with the code below. 但是为了帮助,我在一个球体上绘制一条船,代码如下。

var geometry = new THREE.ShapeGeometry(shape);
var translation = new THREE.Matrix4().makeTranslation(boat.position.x, boat.position.y, boat.position.z);
var rotationZ = new THREE.Matrix4().makeRotationZ(-THREE.Math.degToRad(boat.cap));
var rotationX = new THREE.Matrix4().makeRotationX(-THREE.Math.degToRad(boat.latitude));
var rotationY = new THREE.Matrix4().makeRotationY(Math.PI / 2 + THREE.Math.degToRad(boat.longitude));
var roationXY = rotationY.multiply(rotationX);
geometry.applyMatrix(rotationZ);
geometry.applyMatrix(roationXY );
geometry.applyMatrix(translation);
  1. First, I apply a rotation on Z to define boat cap 首先,我在Z上应用旋转来定义船首
  2. Then, I apply rotation on Y,X to to set the boat perpendicular to the surface of the sphere 然后,我在Y,X上应用旋转以将船垂直于球体表面设置
  3. Finally I apply a translation to put the boat on the surafce of the sphere 最后,我应用翻译将船放在球体上

The rotations order is important 轮换顺序很重要

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM