2016-09-18 64 views
2

这一个是很烦人的。 我正在尝试基于鼠标输入实现Cannon.Body的旋转。 通过使用(Cannon)Three FPS示例来演示,您可以看到问题所在。基于四元数的正确旋转炮身?

https://codepen.io/Raggar/pen/EggaZP https://github.com/RaggarDK/Baby/blob/baby/pl.js

当您运行的代码,并通过点击“点击播放”区域,按W 1秒钟让球进入相机的视野使pointerlockcontrols,你会看到通过施加速度球体根据WASD键移动。如果移动鼠标,则将四元数应用于Body,并计算适当的速度。 现在转动180度,X轴上的旋转现在以某种方式取消。 向上移动鼠标时,球体向下旋转。

如何解决此问题?也许我在其他地方做错了什么,这可能与四元数混乱?

也许我应该提到,在playercontroller(pl.js)中,我将旋转应用于sphereBody,而不是偏航和pitchObjects。

从pl.js(49号线)

相关的代码:

var onMouseMove = function (event) { 

    if (scope.enabled === false) return; 

    var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; 
    var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; 


    cannonBody.rotation.y -= movementX * 0.002; 
    cannonBody.rotation.x -= movementY * 0.002; 

    cannonBody.rotation.x = Math.max(- PI_2, Math.min(PI_2, cannonBody.rotation.x)); 





    //console.log(cannonBody.rotation); 
}; 

和(174线):

euler.x = cannonBody.rotation.x; 
    euler.y = cannonBody.rotation.y; 
    euler.order = "XYZ"; 
    quat.setFromEuler(euler); 
    inputVelocity.applyQuaternion(quat); 
    cannonBody.quaternion.copy(quat); 
    velocity.x = inputVelocity.x; 
    velocity.z = inputVelocity.z; 

里面的动画()函数,codepen(305线): testballMesh.position.copy(sphereBody.position); testballMesh.quaternion.copy(sphereBody.quaternion);

+0

因为pl.js没有正确的mimetype,所以codepen在Chrome中不起作用。修正它在这里:https://codepen.io/anon/pen/PGGpLZ – schteppe

回答

2

问题是你为四元数指定角度的方式。四元数x,y,z,w属性不直接与角度兼容,所以需要转换。

这是如何设置围绕给定轴的角度为CANNON.Quaternion

var axis = new CANNON.Vec3(1,0,0); 
var angle = Math.PI/3; 
body.quaternion.setFromAxisAngle(axis, angle); 

提取欧拉四元数的角度是不太可能让攻击问题的第二部分的最佳方式。你可以,而不是仅仅存储在旋转绕X轴和Y轴,当用户移动鼠标:

// Declare variables outside the mouse handler 
var angleX=0, angleY=0; 

// Inside the handler: 
angleY -= movementX * 0.002; 
angleX -= movementY * 0.002; 
angleX = Math.max(- PI_2, Math.min(PI_2, angleX)); 

然后让旋转的四元数,分别采用两个四元(一个用于X角和一个Y)然后将它们合并到一个:

var quatX = new CANNON.Quaternion(); 
var quatY = new CANNON.Quaternion(); 
quatX.setFromAxisAngle(new CANNON.Vec3(1,0,0), angleX); 
quatY.setFromAxisAngle(new CANNON.Vec3(0,1,0), angleY); 
var quaternion = quatY.mult(quatX); 
quaternion.normalize(); 

四元数适用于您的速度矢量:

var rotatedVelocity = quaternion.vmult(inputVelocity); 

临提示:不要使用欧拉角,如果你能避免。他们通常会造成比他们解决的更多的问题

+0

令人惊叹。 我最初使用setFromAxisAngle,但我认为乘法会混淆和破坏值,通过设置setFromAxisAngle两次,第二个会覆盖第一个。尽管如此,这个工作完美无缺。 至于速度,我确实多次读过欧盟有限制和问题,如果可能的话应该避免。 我会牢记未来。 谢谢;) –