Signatur
Beschreibung
Die schreibgeschützte Eigenschaft transform eines XRPose-Objekts enthält ein XRRigidTransform. Es beschreibt, wo sich ein Objekt befindet und wie es ausgerichtet ist. Bezugsrahmen ist der Basisraum (baseSpace), den du beim Abruf der Pose übergeben hast, etwa mit XRFrame.getPose(space, baseSpace) oder XRFrame.getViewerPose(referenceSpace).
Das Transform besteht aus drei Teilen:
position: einDOMPointReadOnlyin Metern, mitw = 1orientation: ein Einheitsquaternion alsDOMPointReadOnlymatrix: eine 4×4-Matrix alsFloat32Arraymit 16 Werten, spaltenweise gespeichert
Über inverse bekommst du zusätzlich die Umkehrtransformation.
Typische Einsätze sind das Platzieren von 3D-Objekten an Controllern, Händen oder erkannten Flächen, Treffertests und die Berechnung der Kameraposition. Die Matrix kannst du direkt als Modellmatrix an WebGL oder an Bibliotheken wie three.js übergeben. Für die Sichtmatrix einer Kamera brauchst du stattdessen transform.inverse.matrix.
Eine Pose gilt nur für den Frame, in dem sie abgerufen wurde. Frage sie deshalb in jedem Aufruf von requestAnimationFrame neu ab, statt alte Werte zwischenzuspeichern.
Rückgabewert
matrix und inverse. Die Eigenschaft ist schreibgeschützt.Beispiele
Controller-Position pro Frame auslesen
const session = await navigator.xr.requestSession('immersive-vr');
const refSpace = await session.requestReferenceSpace('local-floor');
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
for (const source of session.inputSources) {
if (!source.gripSpace) continue;
const pose = frame.getPose(source.gripSpace, refSpace);
if (!pose) continue; // Tracking verloren
const { position, orientation } = pose.transform;
console.log(
`${source.handedness}: x=${position.x.toFixed(2)} y=${position.y.toFixed(2)} z=${position.z.toFixed(2)}`,
`quat=(${orientation.x.toFixed(2)}, ${orientation.y.toFixed(2)}, ${orientation.z.toFixed(2)}, ${orientation.w.toFixed(2)})`
);
}
};
session.requestAnimationFrame(onFrame);
Modellmatrix an WebGL übergeben
// gl, program, refSpace und modelSpace sind bereits eingerichtet
const uModel = gl.getUniformLocation(program, 'uModelMatrix');
const drawAtPose = (frame) => {
const pose = frame.getPose(modelSpace, refSpace);
if (!pose) return;
// matrix ist ein spaltenweise gespeichertes Float32Array mit 16 Werten
gl.uniformMatrix4fv(uModel, false, pose.transform.matrix);
gl.drawArrays(gl.TRIANGLES, 0, 36);
};
Kopfposition und Sichtmatrix aus der Viewer-Pose
const onFrame = (time, frame) => {
const session = frame.session;
session.requestAnimationFrame(onFrame);
const viewerPose = frame.getViewerPose(refSpace);
if (!viewerPose) return;
const head = viewerPose.transform.position;
console.log(`Kopfhöhe: ${head.y.toFixed(2)} m`);
// Sichtmatrix = Inverse der Pose-Matrix
const viewMatrix = viewerPose.transform.inverse.matrix;
console.log(viewMatrix.length);
};
// Wichtig · Fallstricke
- Nur für den aktuellen Frame gültig: Pose und Transform beschreiben den Zustand im aktuellen
XRFrame. Wer sie über mehrere Frames speichert, bekommt veraltete Werte. Auf ein inaktives Frame darf man ohnehin nicht mehr zugreifen. getPose()kannnullliefern: Das passiert zum Beispiel, wenn das Tracking verloren geht. Prüfe das immer, bevor du auftransformzugreifst.- Geschätzte Werte: Wenn
pose.emulatedPositionden Werttruehat, ist die Position nur geschätzt, etwa bei Geräten mit 3DoF-Tracking. Sie ist dann nicht zuverlässig. - Matrix nicht verändern: Kopiere
transform.matrixvor jeder Änderung, zum Beispiel mitnew Float32Array(transform.matrix). - Modell- oder Sichtmatrix:
matrixist die Modellmatrix, die aus dem Pose-Raum in den Basisraum umrechnet. Die Kamera braucht die Sichtmatrix, alsoinverse.matrix. - Kompatibilität: WebXR funktioniert nur in sicheren Kontexten (HTTPS) und erfordert eine Nutzeraktion, um die Sitzung zu starten. Chromium-Browser und Browser auf XR-Headsets unterstützen es. Firefox und Safari auf dem Desktop unterstützen es nicht; die Emulator-Erweiterung WebXR API Emulator kann beim Testen helfen.