Start · Sprachen · JavaScript · Referenz · XRPose.transform

XRPose.transform

Eigenschaft

Schreibgeschütztes <code>XRRigidTransform</code>, das Position und Orientierung einer Pose relativ zum Basis-<code>XRSpace</code> angibt.

seit JavaScript WebXR Device API; Chrome/Edge 79+, Samsung Interne Kategorie: webapi

Signatur

XRPose.transform

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: ein DOMPointReadOnly in Metern, mit w = 1
  • orientation: ein Einheitsquaternion als DOMPointReadOnly
  • matrix: eine 4×4-Matrix als Float32Array mit 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

Typ
XRRigidTransform
Beschreibung
Die Position (in Metern) und Orientierung (als Quaternion) der Pose relativ zum Basisraum. Zusätzlich enthält das Objekt die Eigenschaften 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);
right: x=0.21 y=1.05 z=-0.34 quat=(0.05, -0.12, 0.01, 0.99)

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);
};
Kopfhöhe: 1.68 m 16

// 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() kann null liefern: Das passiert zum Beispiel, wenn das Tracking verloren geht. Prüfe das immer, bevor du auf transform zugreifst.
  • Geschätzte Werte: Wenn pose.emulatedPosition den Wert true hat, 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.matrix vor jeder Änderung, zum Beispiel mit new Float32Array(transform.matrix).
  • Modell- oder Sichtmatrix: matrix ist die Modellmatrix, die aus dem Pose-Raum in den Basisraum umrechnet. Die Kamera braucht die Sichtmatrix, also inverse.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.