Start · Sprachen · JavaScript · Referenz · XRHitTestResult.getPose()

XRHitTestResult.getPose()

Methode

Liefert die <code>XRPose</code> eines Treffertest-Ergebnisses (Schnittpunkt mit realer Geometrie) relativ zum angegebenen Referenzraum oder <code>null</code>.

seit JavaScript WebXR Hit Test Module; Chrome/Edge 81+ (Android), Kategorie: webapi

Signatur

XRHitTestResult.prototype.getPose(baseSpace)

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

Typ
XRPose | null
Beschreibung
Eine 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);
Treffer bei 0.12, -1.35, -0.87

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);
Objekte platziert: 1

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);
});
Anker-Position: -1.35

// Wichtig · Fallstricke

  • Nur innerhalb des Frames gültig: XRHitTestResult-Objekte gehören zu genau einem XRFrame. Wer getPose() nach Ende des Frame-Callbacks aufruft (z. B. später in einem Timer), löst einen InvalidStateError aus. Innerhalb eines select-Events ist der Aufruf erlaubt, weil der Frame dort noch aktiv ist. Wer die Pose länger braucht, sollte die Matrix kopieren.
  • Immer auf null prüfen, denn das Tracking kann jederzeit verloren gehen.
  • Die Sitzung muss mit dem Feature 'hit-test' angefordert werden (requiredFeatures oder optionalFeatures), sonst schlägt requestHitTestSource() 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.