Start · Sprachen · JavaScript · Referenz · XRBoundedReferenceSpace.boundsGeometry

XRBoundedReferenceSpace.boundsGeometry

Eigenschaft

Schreibgeschütztes Array von <code>DOMPointReadOnly</code>-Punkten, die das Bodenpolygon beschreiben, in dem sich der Nutzer in einer <code>bounded-floor</code>-Sitzung sicher bewegen kann.

seit JavaScript WebXR Device API – Chromium-Browser (Chrome/Edge 7 Kategorie: webapi

Signatur

XRBoundedReferenceSpace.boundsGeometry

Beschreibung

Die Eigenschaft boundsGeometry eines XRBoundedReferenceSpace gibt die Grenze des physischen Spielbereichs an, etwa den Guardian- oder Chaperone-Bereich, den der Nutzer in seinem VR-System eingerichtet hat. Jeder Eintrag ist ein DOMPointReadOnly. Die Punkte liegen auf dem Boden: x und z geben die Position in Metern relativ zum Ursprung des Referenzraums an, y ist immer 0 und w immer 1.

Die Punkte bilden ein geschlossenes Polygon und sind im Uhrzeigersinn angeordnet, von oben auf den Boden gesehen. Der letzte Punkt wird automatisch mit dem ersten verbunden. Das Polygon muss nicht konvex sein. Nützlich ist die Eigenschaft, um die Spielfläche sichtbar zu machen, Inhalte nur innerhalb des erlaubten Bereichs zu platzieren oder den Nutzer zu warnen, wenn er sich dem Rand nähert.

Einen XRBoundedReferenceSpace erhält man über XRSession.requestReferenceSpace('bounded-floor'). Dafür muss man das Merkmal 'bounded-floor' beim Start der Sitzung als requiredFeatures oder optionalFeatures anfordern. Ändert der Nutzer während der Sitzung seine Grenzen, löst der Referenzraum ein reset-Event aus. Danach sollte man boundsGeometry neu auslesen.

Rückgabewert

Typ
ReadonlyArray<DOMPointReadOnly>
Beschreibung
Eingefrorenes Array von Punkten (Meter; y = 0, w = 1), im Uhrzeigersinn angeordnet. Es ist leer, solange keine Grenzen bekannt sind, oder wenn das System sie aus Datenschutzgründen nicht herausgibt.

Beispiele

Bounded-Floor-Raum anfordern und Grenzpunkte ausgeben

const startXR = async () => {
  const session = await navigator.xr.requestSession('immersive-vr', {
    optionalFeatures: ['bounded-floor', 'local-floor']
  });

  try {
    const space = await session.requestReferenceSpace('bounded-floor');
    console.log(`Anzahl Grenzpunkte: ${space.boundsGeometry.length}`);
    space.boundsGeometry.forEach(({ x, z }, i) => {
      console.log(`Punkt ${i}: x=${x.toFixed(2)} m, z=${z.toFixed(2)} m`);
    });
    return { session, space };
  } catch (err) {
    // Fallback, wenn keine Grenzen verfügbar sind
    console.warn('bounded-floor nicht verfügbar, nutze local-floor');
    const space = await session.requestReferenceSpace('local-floor');
    return { session, space };
  }
};

// Muss durch eine Nutzeraktion ausgelöst werden
document.querySelector('#enter-vr').addEventListener('click', startXR);
Anzahl Grenzpunkte: 4 Punkt 0: x=-1.50 m, z=-1.00 m Punkt 1: x=1.50 m, z=-1.00 m Punkt 2: x=1.50 m, z=1.00 m Punkt 3: x=-1.50 m, z=1.00 m

Fläche des Spielbereichs berechnen (Gaußsche Trapezformel)

const playArea = (points) => {
  let sum = 0;
  for (let i = 0; i < points.length; i++) {
    const a = points[i];
    const b = points[(i + 1) % points.length]; // Polygon schließen
    sum += a.x * b.z - b.x * a.z;
  }
  return Math.abs(sum) / 2;
};

// space: XRBoundedReferenceSpace
const area = playArea(space.boundsGeometry);
console.log(`Spielfläche: ${area.toFixed(2)} m²`);
Spielfläche: 6.00 m²

Warnung, wenn der Nutzer den Bereich verlässt

// Punkt-in-Polygon-Test (Ray Casting) auf der x/z-Ebene
const isInside = (px, pz, poly) => {
  let inside = false;
  for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
    const { x: xi, z: zi } = poly[i];
    const { x: xj, z: zj } = poly[j];
    if ((zi > pz) !== (zj > pz) &&
        px < ((xj - xi) * (pz - zi)) / (zj - zi) + xi) {
      inside = !inside;
    }
  }
  return inside;
};

let bounds = space.boundsGeometry;

// Grenzen nach einem Reset neu einlesen
space.addEventListener('reset', () => {
  bounds = space.boundsGeometry;
});

const onFrame = (time, frame) => {
  session.requestAnimationFrame(onFrame);
  const pose = frame.getViewerPose(space);
  if (!pose || bounds.length === 0) return;
  const { x, z } = pose.transform.position;
  if (!isInside(x, z, bounds)) {
    console.warn('Achtung: Spielbereich verlassen!');
  }
};
session.requestAnimationFrame(onFrame);
Achtung: Spielbereich verlassen!

// Wichtig · Fallstricke

  • Browser-Unterstützung: Die Eigenschaft gibt es nur in Chromium-Browsern mit WebXR und in Standalone-Headset-Browsern wie dem Meta Quest Browser. Firefox und Safari unterstützen bounded-floor nicht. WebXR funktioniert außerdem nur in einem sicheren Kontext (HTTPS).
  • Nicht garantiert: requestReferenceSpace('bounded-floor') kann mit NotSupportedError abgelehnt werden, zum Beispiel wenn keine Grenzen eingerichtet sind. Deshalb immer einen Fallback auf 'local-floor' vorsehen.
  • Leeres Array: Das Array kann leer sein, solange das Tracking die Grenzen noch nicht kennt. Vor der Nutzung length prüfen.
  • Koordinaten: Die Punkte gelten nur im Koordinatensystem dieses Referenzraums. Nutzt man getOffsetReferenceSpace(), werden sie entsprechend umgerechnet. Die Höhe (y) ist immer 0, das Polygon beschreibt also nur den Boden.
  • Datenschutz: Die Grenzen verraten etwas über die Raumgröße des Nutzers. Browser können die Werte deshalb vergröbern oder erst nach Zustimmung herausgeben. Die Daten sollte man nicht an Server senden.
  • Nach einem reset-Event können sich die Grenzen geändert haben. Zwischengespeicherte Werte sind dann veraltet.