Signatur
Beschreibung
Die Eigenschaft transform eines XRView-Objekts gibt an, wo sich das virtuelle Auge (bzw. die Kamera) einer einzelnen Ansicht befindet und wohin es blickt. Der Wert ist ein XRRigidTransform und bezieht sich auf den XRReferenceSpace, den man beim Aufruf von XRFrame.getViewerPose(referenceSpace) übergeben hat.
Bei einem stereoskopischen Headset gibt es in der Regel zwei Ansichten (linkes und rechtes Auge), deren Transformationen sich um den Augenabstand unterscheiden. Bei Inline-Sitzungen oder auf Smartphones mit AR gibt es meist nur eine Ansicht.
In der Praxis braucht man vor allem transform.inverse.matrix: Das ist die View-Matrix, die zusammen mit XRView.projectionMatrix an den Vertex-Shader übergeben wird. Außerdem liefern transform.position und transform.orientation Position und Blickrichtung pro Auge, etwa für Raycasting, Audio-Spatialisierung oder Spiegelungen.
Die Eigenschaft ist nur lesbar. Das Objekt ist nur für den aktuellen Frame gültig und wird bei jedem Aufruf von requestAnimationFrame neu erzeugt.
Rückgabewert
position (DOMPointReadOnly), orientation (Quaternion als DOMPointReadOnly), matrix (Float32Array mit 16 Werten, spaltenweise angeordnet) und inverse (die umgekehrte Transformation, also die View-Matrix).Beispiele
View-Matrix pro Auge an WebGL übergeben
// Setzt voraus: session, refSpace, gl, program und uniform-Locations sind bereits eingerichtet
const onXRFrame = (time, frame) => {
const session = frame.session;
session.requestAnimationFrame(onXRFrame);
const pose = frame.getViewerPose(refSpace);
if (!pose) return; // Tracking verloren
const glLayer = session.renderState.baseLayer;
gl.bindFramebuffer(gl.FRAMEBUFFER, glLayer.framebuffer);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
for (const view of pose.views) {
const vp = glLayer.getViewport(view);
gl.viewport(vp.x, vp.y, vp.width, vp.height);
// View-Matrix = Umkehrung der Transformation des Blickpunkts
gl.uniformMatrix4fv(uViewMatrix, false, view.transform.inverse.matrix);
gl.uniformMatrix4fv(uProjectionMatrix, false, view.projectionMatrix);
drawScene();
}
};
session.requestAnimationFrame(onXRFrame);
Position und Orientierung jedes Auges ausgeben
const logEyes = (frame, refSpace) => {
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
for (const view of pose.views) {
const { position: p, orientation: o } = view.transform;
console.log(
`${view.eye}: pos=(${p.x.toFixed(3)}, ${p.y.toFixed(3)}, ${p.z.toFixed(3)}) ` +
`rot=(${o.x.toFixed(2)}, ${o.y.toFixed(2)}, ${o.z.toFixed(2)}, ${o.w.toFixed(2)})`
);
}
};
Blickrichtung aus der Transformationsmatrix bestimmen
// Die Kamera blickt in WebXR entlang der lokalen -Z-Achse.
// Die dritte Spalte der Matrix (Index 8–10) ist die lokale Z-Achse.
const getViewDirection = (view) => {
const m = view.transform.matrix;
return { x: -m[8], y: -m[9], z: -m[10] };
};
const dir = getViewDirection(pose.views[0]);
console.log('Blickrichtung:', dir);
// Wichtig · Fallstricke
- Nicht die Matrix direkt als View-Matrix verwenden:
transform.matrixbeschreibt, wo die Kamera im Raum steht (Kamera → Welt). Für die View-Matrix braucht mantransform.inverse.matrix. Wer das verwechselt, bekommt eine gespiegelte oder „mitlaufende“ Szene. - Der Wert hängt vom Referenzraum ab: Dieselbe Ansicht liefert mit
'local','local-floor'oder'bounded-floor'jeweils andere Koordinaten. - Objekte nicht über Frames hinweg zwischenspeichern:
XRViewund seintransformsind nur innerhalb des aktuellen Frame-Callbacks gültig. Benötigte Werte kopieren (z. B.Float32Array.from(view.transform.matrix)). - Pro Auge rendern: Bei Headsets unterscheiden sich die Transformationen der Ansichten. Nimmt man für beide Augen die Pose des Betrachters (
pose.transform), geht der Stereo-Effekt verloren. getViewerPose()kannnullliefern (z. B. bei Tracking-Verlust), dann gibt es keine Ansichten.- Kompatibilität: WebXR erfordert einen sicheren Kontext (HTTPS) und ist nur in Chromium-basierten Browsern und im Meta Quest Browser verfügbar. Firefox unterstützt die Schnittstelle nicht, Safari nur auf visionOS. Vorab mit
navigator.xr?.isSessionSupported()prüfen.