@iiif/3d-manifesto-dev
Version:
IIIF Presentation API utility library for client and server with 3D extension
162 lines (159 loc) • 7.39 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cameraRelativeRotation = cameraRelativeRotation;
exports.lightRelativeRotation = lightRelativeRotation;
exports.eulerFromRotateTransform = eulerFromRotateTransform;
exports.combineTransformsToMatrix = combineTransformsToMatrix;
exports.combineTransformsToTRS = combineTransformsToTRS;
exports.decomposeMatrix = decomposeMatrix;
var threejs_math_1 = require("threejs-math");
// https://ros2jsguy.github.io/threejs-math/index.html
/**
* performs the calculation required for the lookAt
* property of a camera resource. Determines the
* required angles of two rotations, the first about
* the x axis and the second about the y axis, which will
* rotate the default camera direction (0,0,-1) into the
* direction of the input arguments
*
* Result of calculation is returned as a instance of EulerAngle from the
* threejs-math library. The "axes order" of the EulerAngle is "YXZ": The
* three-js library uses body-fixed axes to represent EulerAngles, which reverse
* the ordering of the "relative rotation" algorithm described in the
* draft 3d api.
* @param direction A vector interpreted as a direction. Client code
* responsible for not passing a 0-length vector, else a
*
* @returns threejs-math.EulerAngle instance
**/
function cameraRelativeRotation(direction) {
if (direction.length() == 0.0)
throw new Error("degenerate geometry: cameraRelativeRotation");
// projDirection is the direction projected onto the xz plane
var projDirection = direction.clone().setComponent(1, 0.0);
var projLength = projDirection.length();
// handle the edge case, desired viewing direction is either straight up
// or straight down
if (projLength == 0.0) {
if (direction.y > 0.0) {
// looking straight up fro below
return new threejs_math_1.Euler(threejs_math_1.MathUtils.degToRad(+90.0), threejs_math_1.MathUtils.degToRad(180.0), 0, "YXZ");
}
else {
return new threejs_math_1.Euler(threejs_math_1.MathUtils.degToRad(-90.0), threejs_math_1.MathUtils.degToRad(180.0), 0, "YXZ");
}
}
var yAngleRad = Math.atan2(-projDirection.x, -projDirection.z);
var xAngleRad = Math.atan2(direction.y, projLength);
return new threejs_math_1.Euler(xAngleRad, yAngleRad, 0.0, "YXZ");
}
/**
* Evaluates the rotation required to transform a directional light
* or spot ling, which in iiif 3D spec
* have an initial direction in the -Y direction, to a direction
* along the input argument
*
* TODO : expand on this documentation taking into account the
* implied specification that RotateTransform instances
* are to be interpreted as an Euler angle definition of
* the rotation
*
* @param direction A vector interpreted as a direction. Client code
* responsible for not passing a 0-length vector, else a
*
* @returns threejs-math.EulerAngle instance
**/
function lightRelativeRotation(direction) {
if (direction.length() == 0.0)
throw new Error("degenerate geometry: cameraRelativeRotation");
var unit_direction = direction.clone().divideScalar(direction.length());
// negative y axis is initial direction of DirectionalLight, SpotLight
// in draft 3D API
var ny_axis = new threejs_math_1.Vector3(0.0, -1.0, 0.0);
var quat = new threejs_math_1.Quaternion().setFromUnitVectors(ny_axis, unit_direction);
var tmp = new threejs_math_1.Euler().setFromQuaternion(quat, "ZXY");
// standard be setting the final intrinsic Y rotation, which is
// along desired direction, to 0
return new threejs_math_1.Euler(tmp.x, 0.0, tmp.z, "ZXY");
}
/**
* Implements the convention that the 3 component values for the RotateTranform
* cass (properties x,y,z) are to be interpreted as Euler angles in the intrinsic XYZ
* order
* @param transform : A object with a Rotation member object, properties x,y,z
*
* @returns threejs-math.EulerAngle instance. From this threejs-math functionsa
* allow conversion to other rotation representations.
**/
function eulerFromRotateTransform(transform) {
var eulerOrder = "XYZ";
var rdata = transform.Rotation;
return new threejs_math_1.Euler(threejs_math_1.MathUtils.degToRad(rdata.x), threejs_math_1.MathUtils.degToRad(rdata.y), threejs_math_1.MathUtils.degToRad(rdata.z), eulerOrder);
}
/**
* Given an array of Transform instances, returns a single Matrix4
* instance that represents the cumulative effect of the transforms
* in the order they appear in the array.
*
* @param transforms An array of Transform instances
*
* @returns A Matrix4 instance representing the cumulative effect of the transforms
**/
function combineTransformsToMatrix(transforms) {
var matrix = new threejs_math_1.Matrix4();
for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) {
var transform = transforms_1[_i];
var tmat = new threejs_math_1.Matrix4();
if (transform.isTranslateTransform) {
var translation = transform.getTranslation();
tmat.makeTranslation(translation.x, translation.y, translation.z);
}
else if (transform.isRotateTransform) {
var euler = eulerFromRotateTransform(transform);
tmat.makeRotationFromEuler(euler);
}
else if (transform.isScaleTransform) {
var scale = transform.getScale();
tmat.makeScale(scale.x, scale.y, scale.z);
}
matrix.premultiply(tmat);
}
return matrix;
}
function combineTransformsToTRS(transforms) {
var translation = new threejs_math_1.Vector3();
var rotation = new threejs_math_1.Euler();
var scale = new threejs_math_1.Vector3(1, 1, 1);
for (var _i = 0, transforms_2 = transforms; _i < transforms_2.length; _i++) {
var transform = transforms_2[_i];
if (transform.isTranslateTransform) {
var translationTransform = transform.getTranslation();
translation.add(new threejs_math_1.Vector3(translationTransform.x, translationTransform.y, translationTransform.z));
}
else if (transform.isRotateTransform) {
var euler = eulerFromRotateTransform(transform);
var q1 = new threejs_math_1.Quaternion().setFromEuler(rotation);
var q2 = new threejs_math_1.Quaternion().setFromEuler(euler);
q1.premultiply(q2);
rotation.setFromQuaternion(q1, "XYZ");
translation.applyEuler(euler);
}
else if (transform.isScaleTransform) {
var scaleTransform = transform.getScale();
var newScale = new threejs_math_1.Vector3(scaleTransform.x, scaleTransform.y, scaleTransform.z);
scale.multiply(newScale);
translation.multiply(newScale);
}
}
return { translation: translation, rotation: rotation, scale: scale };
}
function decomposeMatrix(matrix) {
var translation = new threejs_math_1.Vector3();
var rotation = new threejs_math_1.Euler();
var rotationQuaternion = new threejs_math_1.Quaternion();
var scale = new threejs_math_1.Vector3();
matrix.decompose(translation, rotationQuaternion, scale);
rotation.setFromQuaternion(rotationQuaternion);
return { translation: translation, rotation: rotation, scale: scale };
}
//# sourceMappingURL=Geometry3d.js.map