@pmndrs/xr
Version:
VR/AR for threejs
61 lines (60 loc) • 2.41 kB
JavaScript
export function createGetXRSpaceMatrix(space, referenceSpace) {
return (target, frame) => {
if (space === referenceSpace) {
target.identity();
return true;
}
const resolvedReferenceSpace = typeof referenceSpace === 'function' ? referenceSpace() : referenceSpace;
if (resolvedReferenceSpace == null) {
return false;
}
const pose = frame?.getPose(space, resolvedReferenceSpace);
if (pose == null) {
return false;
}
target.fromArray(pose.transform.matrix);
return true;
};
}
export function getSpaceFromAncestors(object, origin, originReferenceSpace, targetOffsetMatrix) {
// Ensure world matrices are up to date for targetObject and all ancestors
object.updateWorldMatrix(true, false);
targetOffsetMatrix?.copy(object.matrix);
const result = getXRSpaceFromAncestorsRec(object.parent, object, targetOffsetMatrix);
if (result != null) {
return result;
}
if (targetOffsetMatrix != null) {
computeOriginReferenceSpaceOffset(object, origin, targetOffsetMatrix);
}
return originReferenceSpace;
}
function computeOriginReferenceSpaceOffset(object, origin, target) {
object.updateWorldMatrix(true, false);
if (origin == null) {
target.copy(object.matrixWorld);
return;
}
origin.updateWorldMatrix(true, false);
//origin * offset = space <=>
//target = origin.matrixWorld-1 * object.matrixWorld
target.copy(origin.matrixWorld).invert().multiply(object.matrixWorld);
}
/**
* Recursively searches ancestors for an xrSpace.
* @requires The world matrices of object, all its ancestors, and the world matrix of targetObject must be up to date.
*/
function getXRSpaceFromAncestorsRec(object, targetObject, targetOffsetMatrix) {
if (object == null) {
return undefined;
}
if (object.xrSpace != null) {
// Calculate offset using world matrices instead of accumulating local matrices.
// This correctly handles components that override updateWorldMatrix (e.g., UIKit Content).
if (targetOffsetMatrix != null) {
targetOffsetMatrix.copy(object.matrixWorld).invert().multiply(targetObject.matrixWorld);
}
return object.xrSpace;
}
return getXRSpaceFromAncestorsRec(object.parent, targetObject, targetOffsetMatrix);
}