2016-09-18 7 views
2

Эта мелодия меня немного раздражает. Я пытаюсь добиться вращения Cannon.Body на основе ввода мыши. Используя пример (Cannon) Three FPS для демонстрации, вы можете видеть, в чем проблема.Обработка правильного вращения тела пушки на основе кватерниона?

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

При запуске кода и включить pointerlockcontrols, нажав на «нажать, чтобы играть в» области и нажмите кнопку W в течение 1 секунды, чтобы получить сферу в поле зрения камеры, вы увидите что шар движется по клавишам WASD, применяя скорость. Если вы перемещаете мышь, кватернион применяется к телу, и вычисляется соответствующая скорость. Теперь поверните на 180 градусов, и вращение по оси X теперь каким-то образом отменено. При перемещении мыши сфера поворачивается вниз.

Как решить такую ​​проблему? Может быть, я что-то делаю неправильно в другом месте, это может испортить кватернион?

Возможно, я должен упомянуть, что в playercontroller (pl.js) я применяю поворот к сфереBody вместо объектов yaw- и 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

Код не работает в Chrome, так как pl.js не имеет правильного типа. Исправлено: 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); 

Распаковка углы Эйлера от кватернионов, вероятно, не лучший способ атаковать вторую часть проблемы. Вы могли бы вместо того, чтобы просто сохранить вращение вокруг осей Х и 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); 

Pro совет: не используйте углы Эйлера, если вы можете избежать их. Они обычно вызывают больше проблем, чем они решают.

+0

Удивительно. Я сначала пошел с setFromAxisAngle, но я думал, что умножение испортит и испортит значения, и, дважды установив setFromAxisAngle, второй будет переопределять первый. Это работает безупречно. А что касается скорости, я читал несколько раз, что у эйлеров есть ограничения и проблемы, и их следует избегать, если это возможно. Я буду помнить об этом в будущем. Спасибо;) –