Получение угла Эйлера от VRPose.orientation Quarternion - PullRequest
0 голосов
/ 24 августа 2018

Мне нужно получить угол тета между направлением телефона и горизонтом (см. Рис.).

enter image description here

Для этого я использую библиотеку polyfill web-vr, которая позволяет мне получить доступ к VRPose.orientation, ориентация камеры каккватернион.

Теперь я пытаюсь преобразовать кватернион в угол Эйлера, чтобы получить нужный мне угол тета , но при моих попытках этот угол не зависит отдругие углы поворота (т. е. если пользователь поворачивается из своего положения, сохраняя телефон в той же ориентации, угол тета изменяется).

Это мой код.

  var orientation = frameData.pose.orientation
  var a = orientation[0]
  var b = orientation[1]
  var c = orientation[2]
  var d = orientation[3]

  var yaw, pitch, roll

  roll = Math.atan(2*(a*b + c*d)/(pow2(a) - pow2(b) - pow2(c) + pow2(d)))

  pitch = - Math.asin(2*(b*d - a*c))

  theta = Math.atan(2*(a*d + b*c)/(pow2(a) + pow2(b) - pow2(c) - pow2(d)))

Есть идеи, что я делаю не так или предложение другого решения?

Спасибо

1 Ответ

0 голосов
/ 25 августа 2018

Вы можете применить кватернион к единичному вектору, а затем вычислить угол:

const vec = new THREE.Vector3();

function getCameraAngle() {
  // Reset the vector to a unit vector pointing into the scene
  vec.set(0, 0, -1);
  // Apply the camera quaternion
  vec.applyQuaternion(camera.quaternion);
  // Calculate the angle based on Y
  return Math.asin(vec.y) * THREE.Math.RAD2DEG;
}

const angle = document.getElementById('angle');

function animate() {
  angle.textContent = getCameraAngle().toFixed(2);
  renderer.render(scene, camera);
};


// Boilerplate
new WebVRPolyfill();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const scene = new THREE.Scene();

const renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.vr.enabled = true;
document.body.appendChild(renderer.domElement);
WEBVR.createButton(renderer);

scene.add(new THREE.AmbientLight('white', 1));

let grid = new THREE.GridHelper();
scene.add(grid);
grid = new THREE.GridHelper();
grid.rotation.x = Math.PI / 2;
grid.position.set(0, 5, -5);
scene.add(grid);
grid = new THREE.GridHelper();
grid.rotation.x = Math.PI / 2;
grid.position.set(0, 5, 5);
scene.add(grid);
grid = new THREE.GridHelper();
grid.rotation.x = Math.PI / 2;
grid.rotation.z = Math.PI / 2;
grid.position.set(5, 5, 0);
scene.add(grid);
grid = new THREE.GridHelper();
grid.rotation.x = Math.PI / 2;
grid.rotation.z = Math.PI / 2;
grid.position.set(-5, 5, 0);
scene.add(grid);
grid = new THREE.GridHelper();
grid.position.set(0, 10, 0);
scene.add(grid);

renderer.setAnimationLoop(animate);

window.addEventListener("resize", () => {
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
});
body {
  margin: 0;
  font-size: 0;
}

#angle {
  position: absolute;
  top: 10px;
  left: 10px;
  background: white;
  font-size: 20pt;
  font-family: monospace;
  padding: 0.2em;
}
<script src="https://unpkg.com/webvr-polyfill@0.10.6/build/webvr-polyfill.min.js"></script>
<script src="https://unpkg.com/three@0.95.0/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.95.0/examples/js/vr/WebVR.js"></script>

<span id="angle"></span>
...