@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
65 lines (64 loc) • 2.4 kB
JavaScript
;
import { Euler, Quaternion, Vector3, Object3D } from "three";
import { degToRad, radToDeg } from "three/src/math/MathUtils";
export const CHANGE_EVENT = { type: "change" };
export const EPS = 1e-6;
export const PI_DEG = radToDeg(Math.PI);
export const PI_DEG2 = 2 * radToDeg(Math.PI);
const AXIS_Z = new Vector3(0, 0, 1);
const euler = new Euler();
const q0 = new Quaternion();
const q1 = new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
const q2 = new Quaternion();
const ROTATION_ORDER_YXZ = "YXZ";
function _setQuaternionFromAlphaBetaGamma(alpha, beta, gamma, orient, target) {
euler.set(beta, alpha, -gamma, ROTATION_ORDER_YXZ);
target.setFromEuler(euler);
target.multiply(q1);
target.multiply(q0.setFromAxisAngle(AXIS_Z, -orient));
}
const alphaOffset = 0;
export function setQuaternionFromEvent(event, screenOrientation, target) {
const alpha = event.alpha ? degToRad(event.alpha) + alphaOffset : 0;
const beta = event.beta ? degToRad(event.beta) : 0;
const gamma = event.gamma ? degToRad(event.gamma) : 0;
const orient = screenOrientation ? degToRad(screenOrientation) : 0;
_setQuaternionFromAlphaBetaGamma(alpha, beta, gamma, orient, target);
}
export function quaternionYAngle(relativeQuaternion) {
euler.setFromQuaternion(relativeQuaternion);
return -radToDeg(euler.y);
}
export function yAngleFromEvent(event, screenOrientation) {
setQuaternionFromEvent(event, screenOrientation, q2);
return quaternionYAngle(q2);
}
function _createObjects() {
const ryOffset = new Object3D();
const ry = new Object3D();
const rx = new Object3D();
const rz = new Object3D();
ryOffset.add(ry);
ry.add(rx);
rx.add(rz);
return {
ryOffset,
ry,
rx,
rz
};
}
let _rotationHierarchy;
function _getRotationHierarchy() {
return _rotationHierarchy || (_rotationHierarchy = _createObjects());
}
export function blendQuaternionToAbsoluteYAngle(relativeQuaternion, yAngleOffset, target) {
euler.setFromQuaternion(relativeQuaternion);
const rotationHierarchy = _getRotationHierarchy();
rotationHierarchy.ryOffset.rotation.set(0, -degToRad(yAngleOffset), 0);
rotationHierarchy.ry.rotation.set(0, euler.y, 0);
rotationHierarchy.rx.rotation.set(euler.x, 0, 0);
rotationHierarchy.rz.rotation.set(0, 0, euler.z);
rotationHierarchy.rz.updateWorldMatrix(true, true);
target.setFromRotationMatrix(rotationHierarchy.rz.matrixWorld);
}