使用有界參考空間
在 WebXR API 中可用的各種參考空間中,bounded-floor 參考空間有些獨特。它不僅由一個獨特的子類 XRBoundedReferenceSpace 表示,而且是唯一一個根據現實世界施加的限制而非虛擬限制來限制移動的參考空間。本文將探討由 XRBoundedReferenceSpace 表示的有限參考空間,描述它們是什麼以及如何使用它們。
有限參考空間有許多用途,包括虛擬繪畫工作室或 3D 建造、建模或雕刻系統;培訓模擬或課程場景;舞蹈或其他基於表演的遊戲;或者使用增強現實在現實世界中預覽 3D 物件等專案。
簡介
有限參考空間表示一個 XR 環境,使用者可以在其中在現實世界中進行物理移動,同時被 XR 硬體跟蹤,其移動隨後被轉換到模擬中。因此,由有限參考空間建立的邊界表示了使用者在模擬中移動時,其現實世界環境中可安全透過、可跟蹤的空間的邊緣。
依賴項
因為有限參考空間建立了一個使用者可以移動的有限區域,所以它自然地限制了模擬環境的大小。如果你將使用者的真實世界運動對映到虛擬環境中,建立一個比使用者可用物理空間更大的虛擬世界是很困難的(而且可能會相當令人困惑)。想象一下,如果你每走一步就移動 100 米,那會多麼不舒服!
那麼,有限參考空間的要求是:
- 能夠跟蹤使用者在現實世界中移動的 XR 硬體,例如基於攝像頭的系統。
- 有足夠安全移動空間的物理空間。
基礎知識
所有有限參考空間的參考空間型別都是 bounded-floor。這是目前唯一可用的有限參考空間型別;在所有其他型別中,如果需要邊界,則必須自行管理。
由於 bounded-floor 是一個地面繫結的參考空間,使用者從空間的地面開始,這在考慮到實際世界影響時是合理的。因此,有限參考空間的起點總是將 Y=0 平面置於地面水平。邊界隨後使用一個 2D 座標陣列定義,只指定 X 和 Z 分量,因為 Y 總是 0。這些點以順時針方向圍繞房間。
請注意,如果底層平臺定義了固定的房間尺度原點和邊界,它可能會將任何未初始化的值初始化為與預定義資訊匹配;對於這些平臺的使用者來說,這並非意外行為。
邊界內部的空間就是使用者的安全移動區域,在該區域內,使用者被跟蹤,其移動被複制到虛擬世界中。雖然使用者的 XR 系統可能會提供自動檢測和防止離開安全區域的功能,但始終建議自行處理,監測使用者位置與世界邊界之間的碰撞,並提供指導以移回原點,或至少留在安全區域內。
沒有固有邊界定義的 XR 硬體可能支援也可能不支援有限參考空間。如果支援,它可能有一個系統,允許使用者在使用有限空間時指定或選擇要應用的邊界。然而,裝置完全有可能拒絕支援任何有限空間,因此您應該準備好回退到其他型別的參考空間。
理解邊界
如前所述,邊界被定義為位於地面水平的一組點,每個點定義邊界區域的一個角,以順時針方式圍繞原點。這在下圖中有所展示。
此圖定義了房間的邊界,原點位於中心,並有一組 12 個點代表可用物理空間的頂點。房間中有兩個切出區域,可能代表使用者身後的沙發、長沙發或長凳,以及放置電腦或其他硬體的支架或桌子。正如這所暗示的,安全區域不要求是凸形的,但可以有任意數量的凹陷或突出部分,只要它是一個連續的形狀。
請注意,此處原點的座標 (0, 0) 表明邊界是在地面水平定義的,並且本質上是地板上的 2D 形狀,就像用來防止寵物離家的隱形圍欄一樣。這裡的完整座標將是 (0, 0, 0)。
此邊界在 XRBoundedReferenceSpace 中的 XRBoundedReferenceSpace 屬性 boundsGeometry 中維護。此屬性包含一個 DOMPointReadOnly 物件陣列,每個物件定義構成空間邊界的一個點,以順時針順序圍繞房間移動。陣列中的每個頂點都有一個 y 座標為 0,因為整個邊界是在地面水平定義的,向上延伸到天花板或無限。每個點的 w 也總是 1。
邊界區域的內部始終被視為在邊界的右側。透過按順時針順序列出點,邊界被放置在定義的形狀內部。如果點以逆時針順序列出,則表示安全區域位於邊界外部,這可能會導致不良結果。
您應該考慮主動檢查使用者是否接近邊界。這對於他們的安全(以防邊界代表某種物理障礙)和避免在邊界附近精度可能降低的情況都很有用。它也很有用,因為使用者可能沉浸在遊戲或其他活動中,沒有意識到他們正在接近邊界,並且如果他們超出跟蹤範圍(尤其是如果這樣做導致他們輸掉遊戲),可能會感到困惑或沮喪。
最簡單的解決方案是簡單地將每個邊界段視為一個用於碰撞檢測的物件。當用戶靠近邊界時,您可以顯示訊息、閃爍警告指示器、播放音訊警告等來警告他們。如果使用者確實與邊界發生碰撞,不要讓他們繼續越過它。
建立有限參考空間
在建立依賴有限參考空間的專案之前,重要的是要記住並非所有 XR 裝置都能夠建立它們。從本質上講,有限參考空間具有特殊的硬體要求,因為它們需要允許使用者在物理空間中移動,同時其移動被跟蹤。在本節中,我們將探討如何安全地建立一個無論是否支援有限空間都能工作的會話。
安全建立有限優先空間
在實際嘗試建立有限參考空間之前,您需要建立一個支援它們的會話。由於並非所有硬體都支援有限參考空間,因此您應該確保將有限參考空間作為可選功能而不是必需功能來支援,除非您對程式碼將執行的環境有特殊瞭解。您可以透過使用以下程式碼建立一個會話來支援 bounded-floor 參考空間(如果可用):
async function onActivateXRButton(event) {
if (!xrSession) {
navigator.xr
.requestSession("immersive-vr", {
requiredFeatures: ["local-floor"],
optionalFeatures: ["bounded-floor"],
})
.then((session) => {
xrSession = session;
startSessionAnimation();
});
}
}
此函式在使用者單擊按鈕啟動 XR 體驗時呼叫,像往常一樣工作,如果會話已存在則立即退出,然後使用 immersive-vr 模式請求新會話。請求會話時指定的選項表明,會話至少必須與 local-floor 參考空間相容,但如果也支援 bounded-floor 空間會更好。
會話建立後,我們的 startSessionAnimation() 函式可以嘗試建立一個 bounded-floor 參考空間,如果失敗,則可以回退到請求一個 local-floor 參考空間(在這種情況下,我們將不得不自行處理邊界)。
這樣,無論使用者的平臺是否能夠提供有限參考空間,我們的會話都將啟動。
建立參考空間
在呼叫 XRSystem 方法 requestSession() 時請求支援 bounded-floor 不足以獲得有限空間。您還需要在呼叫 requestReferenceSpace() 時請求一個。這意味著您需要更改呼叫 requestReferenceSpace() 的程式碼以請求有限參考空間,如果失敗則回退到您的備用選擇,如下所示:
let xrSession = null;
let xrReferenceSpace = null;
let spaceType = null;
function onSessionStarted(session) {
xrSession = session;
spaceType = "bounded-floor";
xrSession
.requestReferenceSpace(spaceType)
.then(onRefSpaceCreated)
.catch(() => {
spaceType = "local-floor";
xrSession
.requestReferenceSpace(spaceType)
.then(onRefSpaceCreated)
.catch(handleError);
});
}
function onRefSpaceCreated(refSpace) {
xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(xrSession, gl),
});
// Now set up matrices, create a secondary reference space to
// transform the viewer's pose, and so forth.
xrSession.requestAnimationFrame(onDrawFrame);
}
如果您將此程式碼與使用無限參考空間的示例中使用的程式碼進行比較,您會確認,最大的區別確實是參考空間型別 bounded-floor。
程式碼首先嚐試獲取一個 bounded-floor 參考空間,但如果失敗,它會請求一個 local-floor 空間。在任何一種情況下,成功獲取參考空間都會將新空間傳遞給函式 onRefSpaceCreated()。如果兩種型別的空間都無法建立,則會呼叫錯誤處理程式 (handleError())。
在任何一種情況下,一旦建立了參考空間,它就會被傳遞給一個名為 onRefSpaceCreated() 的函式,該函式接管設定空間以供使用的過程。
然而,重要的是要記住,雖然 local-floor 空間提供了一個相對於地面的空間並且總是可用於沉浸式會話,但它與 bounded-floor 也有顯著差異,因此您需要準備好處理這些差異。這就是為什麼上面的程式碼片段將正在使用的參考空間記錄在變數 spaceType 中。最明顯的區別是 local-floor 空間不提供邊界,並且主要用於使用者在會話期間停留在原地的情況。
如果在嘗試建立 local-floor 參考空間時,使用者的 XR 裝置沒有內建支援來確定地面水平,WebXR 層仍將建立一個 local-floor 空間。但是,地面水平將透過選擇和模擬地面水平並透過固定量向上移動檢視來模擬,以確保場景內容在正確的位置渲染。
請記住,預設情況下,觀看者的位置緊貼地板,就像一個放在地上的攝像頭。如果您希望模擬人類對場景的視角,您可能希望透過將檢視向上移動一個近似人類眼睛高度的距離來轉換它,方法是向 XRReferenceSpace 方法 getOffsetReferenceSpace() 提供一個適當的變換矩陣。
這將把上面程式碼片段中的 onRefSpaceCreated() 方法更改為:
function onRefSpaceCreated(refSpace) {
xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(xrSession, gl),
});
let startPosition = vec3.fromValues(0, 1.5, 0);
const startOrientation = vec3.fromValues(0, 0, 1.0);
xrReferenceSpace = xrReferenceSpace.getOffsetReferenceSpace(
new XRRigidTransform(startPosition, startOrientation),
);
xrSession.requestAnimationFrame(onDrawFrame);
}
在此程式碼中,在參考空間建立後執行,我們建立了一個 XRRigidTransform,表示將檢視向上移動 1.5 米的變換。這近似於人類的高度,儘管它假設我們之前已經轉換了座標系,因此每個座標的值不再受限於 -1 到 1,同時保持值 1 表示一米的定義)。
新的變換被傳遞給 getOffsetReferenceSpace() 以獲取一個參考空間,該空間對映基本座標系和渲染影像的座標之間的關係。新的參考空間替換了原始空間。最後,透過呼叫 XRSession 方法 requestAnimationFrame() 來開始繪圖。