Signatur
Beschreibung
getPose() gibt an, wo ein Treffertest (Hit Test) in der realen Umgebung eingeschlagen hat, also z. B. auf dem Boden, einem Tisch oder einer Wand. Heraus kommt eine XRPose. Deren transform enthält Position und Ausrichtung des Treffers, bezogen auf den übergebenen Basisraum (XRSpace).
Typischerweise nutzt man die Methode in AR-Anwendungen (immersive-ar) in der Render-Schleife. Man holt sich pro Frame mit XRFrame.getHitTestResults() die Ergebnisse einer XRHitTestSource, nimmt meist das erste (nächstgelegene) Ergebnis und ruft darauf getPose(referenceSpace) auf. Mit der Pose positioniert man dann ein Fadenkreuz (Reticle) oder setzt ein virtuelles Objekt auf eine erkannte Fläche.
Die Y-Achse der zurückgegebenen Pose zeigt entlang der Flächennormalen, also von der getroffenen Oberfläche weg. Die Matrix pose.transform.matrix (ein Float32Array mit 16 Werten, spaltenweise angeordnet) kann direkt an WebGL oder three.js übergeben werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $baseSpace Pflicht | XRSpace | Referenzraum, relativ zu dem die Pose berechnet wird – meist der XRReferenceSpace aus session.requestReferenceSpace('local'). |
Rückgabewert
XRPose mit transform (Position und Orientierung des Treffers) und emulatedPosition. Gibt null zurück, wenn sich die Pose relativ zu baseSpace gerade nicht bestimmen lässt.Beispiele
Fadenkreuz auf erkannter Fläche positionieren
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['hit-test']
});
const viewerSpace = await session.requestReferenceSpace('viewer');
const localSpace = await session.requestReferenceSpace('local');
const hitTestSource = await session.requestHitTestSource({ space: viewerSpace });
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
const results = frame.getHitTestResults(hitTestSource);
if (results.length > 0) {
const pose = results[0].getPose(localSpace);
if (pose) {
const { x, y, z } = pose.transform.position;
console.log(`Treffer bei ${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`);
// reticle.matrix.fromArray(pose.transform.matrix);
}
}
};
session.requestAnimationFrame(onFrame);
Objekt beim Tippen platzieren (select-Event)
let latestHit = null;
const placed = [];
const onFrame = (time, frame) => {
frame.session.requestAnimationFrame(onFrame);
const [hit] = frame.getHitTestResults(hitTestSource);
latestHit = hit ?? null;
};
session.addEventListener('select', (event) => {
if (!latestHit) return;
const pose = latestHit.getPose(localSpace);
if (!pose) return;
// Kopie der Matrix speichern, da das Objekt nur im Frame gültig ist
placed.push(Float32Array.from(pose.transform.matrix));
console.log('Objekte platziert:', placed.length);
});
session.requestAnimationFrame(onFrame);
Anker aus Treffer erzeugen (stabile Platzierung)
session.addEventListener('select', async () => {
if (!latestHit?.createAnchor) return; // Anchors-Modul optional
const anchor = await latestHit.createAnchor();
const onFrame = (t, frame) => {
frame.session.requestAnimationFrame(onFrame);
const pose = frame.getPose(anchor.anchorSpace, localSpace);
if (pose) console.log('Anker-Position:', pose.transform.position.y.toFixed(2));
};
session.requestAnimationFrame(onFrame);
});
// Wichtig · Fallstricke
- Nur innerhalb des Frames gültig:
XRHitTestResult-Objekte gehören zu genau einemXRFrame. WergetPose()nach Ende des Frame-Callbacks aufruft (z. B. später in einem Timer), löst einenInvalidStateErroraus. Innerhalb einesselect-Events ist der Aufruf erlaubt, weil der Frame dort noch aktiv ist. Wer die Pose länger braucht, sollte die Matrix kopieren. - Immer auf
nullprüfen, denn das Tracking kann jederzeit verloren gehen. - Die Sitzung muss mit dem Feature
'hit-test'angefordert werden (requiredFeaturesoderoptionalFeatures), sonst schlägtrequestHitTestSource()fehl. - Für Objekte, die dauerhaft an einer Stelle bleiben sollen, eignen sich Anker (
createAnchor()) besser. Eine einmal gespeicherte Pose driftet, wenn das System sein Weltverständnis aktualisiert. - Kompatibilität: Nur in sicheren Kontexten (HTTPS). Unterstützt in Chromium auf Android mit ARCore und im Meta Quest Browser. Firefox und Safari unterstützen die Methode nicht, daher vorher
navigator.xr.isSessionSupported('immersive-ar')prüfen.