Signatur
Beschreibung
getPose() berechnet für den Zeitpunkt des aktuellen XRFrame, wo sich ein Raum (XRSpace) im Verhältnis zu einem anderen Raum befindet. Das Ergebnis ist ein XRPose-Objekt mit einer transform (XRRigidTransform mit position, orientation und matrix) und dem Flag emulatedPosition.
Typische Einsatzfälle sind das Verfolgen von Eingabegeräten: Über inputSource.gripSpace ermittelt man, wo ein Controller in der Hand liegt (um z. B. ein 3D-Modell daran zu hängen), über inputSource.targetRaySpace den Zeigestrahl für Auswahl und Raycasting. Auch Anker (XRAnchor.anchorSpace) oder die Gelenke der Handverfolgung (dafür gibt es zusätzlich getJointPose()) werden so abgefragt.
Für die Pose des Betrachters selbst (Kopf bzw. Augen) nutzt man stattdessen XRFrame.getViewerPose(), das zusätzlich die einzelnen XRViews für das Rendern liefert. Als baseSpace übergibt man in der Regel den Referenzraum, der auch zum Rendern verwendet wird, etwa den von requestReferenceSpace("local-floor").
Die Methode darf nur mit einem aktiven Frame aufgerufen werden, also innerhalb des Callbacks von XRSession.requestAnimationFrame() oder eines Eingabe-Events wie select. Kann das Gerät die Beziehung zwischen den beiden Räumen gerade nicht bestimmen (z. B. weil der Controller die Verfolgung verloren hat), gibt sie null zurück.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $space Pflicht | XRSpace | — | Der Raum, dessen Pose gesucht ist – z. B. inputSource.gripSpace, inputSource.targetRaySpace oder anchor.anchorSpace. |
| $baseSpace Pflicht | XRSpace | — | Der Bezugsraum, in dessen Koordinatensystem die Pose ausgedrückt wird, üblicherweise ein XRReferenceSpace. |
Rückgabewert
XRPose mit transform (Position in Metern, Orientierung als Quaternion, 4×4-matrix) und emulatedPosition; optional auch linearVelocity/angularVelocity. null, wenn die Pose aktuell nicht bestimmbar ist.Beispiele
Controller-Position in jedem 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 frame.session.inputSources) {
if (!source.gripSpace) continue; // z. B. Blick-Eingabe ohne Grip
const pose = frame.getPose(source.gripSpace, refSpace);
if (pose) {
const { x, y, z } = pose.transform.position;
console.log(`${source.handedness}: ${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`);
}
}
};
session.requestAnimationFrame(onFrame);
Zeigestrahl beim select-Event auswerten
session.addEventListener('select', (event) => {
const { frame, inputSource } = event;
const rayPose = frame.getPose(inputSource.targetRaySpace, refSpace);
if (!rayPose) return;
const origin = rayPose.transform.position;
// Blickrichtung: -Z-Achse der Transformationsmatrix
const m = rayPose.transform.matrix;
const direction = { x: -m[8], y: -m[9], z: -m[10] };
console.log('Strahl von', origin, 'Richtung', direction);
});
Matrix direkt an ein 3D-Modell übergeben (Three.js)
const controllerMesh = new THREE.Mesh(
new THREE.BoxGeometry(0.05, 0.05, 0.15),
new THREE.MeshStandardMaterial({ color: 0x3399ff })
);
controllerMesh.matrixAutoUpdate = false;
scene.add(controllerMesh);
const updateController = (frame, source) => {
const pose = frame.getPose(source.gripSpace, refSpace);
controllerMesh.visible = pose !== null;
if (pose) {
controllerMesh.matrix.fromArray(pose.transform.matrix);
// Hinweis bei geschätzter Position anzeigen
controllerMesh.material.opacity = pose.emulatedPosition ? 0.5 : 1;
}
};
// Wichtig · Fallstricke
- Immer auf
nullprüfen: Verliert das Gerät die Verfolgung, liefertgetPose()null– ohne Prüfung folgt einTypeErrorbeim Zugriff auftransform. - Nur mit aktivem Frame: Wird ein
XRFrameaußerhalb seines Callbacks aufgerufen (z. B. in einem gespeicherten Verweis oder nachawait), wird eineInvalidStateError-DOMExceptiongeworfen. Frames nicht zwischenspeichern. - Beide Räume müssen zur selben
XRSessiongehören, sonst wird ebenfalls eineInvalidStateErrorgeworfen. emulatedPosition === truebedeutet, dass die Position nur geschätzt ist (z. B. bei 3DoF-Controllern). Die Orientierung ist dann verlässlich, die Position nicht.gripSpacekannundefinedsein (z. B. bei Blick- oder Bildschirm-Eingabe);targetRaySpaceist immer vorhanden.- Für die Kopfpose
getViewerPose()verwenden, für HandgelenkegetJointPose(). - Kompatibilität: WebXR erfordert einen sicheren Kontext (HTTPS) und wird von Chromium-basierten Browsern und dem Meta Quest Browser unterstützt; Firefox und Desktop-Safari unterstützen es nicht (Safari auf Apple Vision Pro dagegen schon). Zum Testen am Desktop eignet sich ein WebXR-Emulator.