UNPKG

@pmndrs/uikit

Version:

Build performant 3D user interfaces with Three.js and yoga.

71 lines (70 loc) 3.23 kB
import { computed } from '@preact/signals-core'; import { Euler, Matrix4, Quaternion, Vector3 } from 'three'; import { alignmentXMap, alignmentYMap } from './utils.js'; import { toAbsoluteNumber } from './text/utils.js'; const tHelper = new Vector3(); const sHelper = new Vector3(); const originVector = new Vector3(); const matrixHelper = new Matrix4(); const eulerHelper = new Euler(); const quaternionHelper = new Quaternion(); const toRad = Math.PI / 180; function toQuaternion([x, y, z]) { return quaternionHelper.setFromEuler(eulerHelper.set(x * toRad, y * toRad, z * toRad)); } const defaultTransformOriginX = 'center'; const defaultTransformOriginY = 'center'; export function computedTransformMatrix({ relativeCenter, size, properties, root, }) { //B * O^-1 * T * O //B = bound transformation matrix //O = matrix to transform the origin for matrix T //T = transform matrix (translate, rotate, scale) return computed(() => { if (relativeCenter.value == null) { return undefined; } const [x, y] = relativeCenter.value; const pixelSize = properties.value.pixelSize; const result = new Matrix4().makeTranslation(x * pixelSize, y * pixelSize, 0); let originCenter = true; const tOX = properties.value.transformOriginX ?? defaultTransformOriginX; const tOY = properties.value.transformOriginY ?? defaultTransformOriginY; if (tOX != 'center' || tOY != 'center') { if (size.value == null) { return undefined; } const [width, height] = size.value; originCenter = false; originVector.set(-alignmentXMap[tOX] * width * pixelSize, -alignmentYMap[tOY] * height * pixelSize, 0); result.multiply(matrixHelper.makeTranslation(originVector)); originVector.negate(); } const tTX = properties.value.transformTranslateX ?? 0; const tTY = properties.value.transformTranslateY ?? 0; const tTZ = properties.value.transformTranslateZ ?? 0; const tRX = properties.value.transformRotateX ?? 0; const tRY = properties.value.transformRotateY ?? 0; const tRZ = properties.value.transformRotateZ ?? 0; const tSX = properties.value.transformScaleX ?? 1; const tSY = properties.value.transformScaleY ?? 1; const tSZ = properties.value.transformScaleZ ?? 1; const r = [tRX, tRY, tRZ]; const t = [ toAbsoluteNumber(tTX, () => size.value?.[0] ?? 0, root.value), -toAbsoluteNumber(tTY, () => size.value?.[1] ?? 0, root.value), tTZ, ]; const s = [ toAbsoluteNumber(tSX, () => 1, root.value), toAbsoluteNumber(tSY, () => 1, root.value), toAbsoluteNumber(tSZ, () => 1, root.value), ]; if (t.some((v) => v != 0) || r.some((v) => v != 0) || s.some((v) => v != 1)) { result.multiply(matrixHelper.compose(tHelper.fromArray(t).multiplyScalar(pixelSize), toQuaternion(r), sHelper.fromArray(s))); } if (!originCenter) { result.multiply(matrixHelper.makeTranslation(originVector)); } return result; }); }