2016-09-18 5 views
2

이것은 나를 꽤 많이 괴롭 히고 있습니다. 나는 대포의 회전을 얻으려고하고있다. 마우스 입력에 기초한 바디. (대포) 세 FPS 예제를 사용하여 문제를 확인할 수 있습니다. https://github.com/RaggarDK/Baby/blob/baby/pl.js쿼터니언 기반 캐논 바디의 올바른 회전 처리?

코드를 실행하고 카메라의 뷰에 영역을 얻기 위해 1 초 "재생 클릭"영역을 누릅니다 W를 클릭하여 pointerlockcontrols 수 있도록

https://codepen.io/Raggar/pen/EggaZP, 당신은 볼 수 있습니다 구가 속도를 적용하여 WASD 키에 따라 움직이는 것입니다. 마우스를 움직이면 쿼터니온이 몸체에 적용되고 적절한 속도가 계산됩니다. 이제 180도 회전하면 X 축의 회전이 이제 어떻게 든 무효화됩니다. 마우스를 위로 움직이면 구가 아래로 회전합니다.

어떻게 이러한 문제를 해결할 수 있습니까? 어쩌면 다른 곳에서 뭔가 잘못하고있는 것일 수도 있습니다. 그러면 쿼터니언이 엉망이 될 수 있을까요?

아마 playercontroller (pl.js)에서 yaw 및 pitchObject 대신 sphereBody에 회전을 적용해야합니다.

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) codepen 애니메이션]() 함수 내부

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; 

(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); 

. 쿼터니언으로 회전을 얻기 위해 다음

// 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에 대한 하나)이 개 사원 수를 사용 : 당신은 대신 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을 두 번 설정하면 두 번째가 우선 적용됩니다. 이것은 완벽하게 작동합니다. 그리고 속도에 관해서는, 나는 오일러가 한계와 문제점을 여러 번 읽었으며, 가능하다면 그것들을 피해야한다고했습니다. 나는 미래를 염두에 두겠다. 감사합니다;) –