Использование ограниченных пространств отсчета
Среди различных пространств отсчета, доступных в наборе API WebXR, 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 (в котором мы должны будем сами обрабатывать границы).
Таким образом, наш сеанс будет запущен независимо от того, поддерживает ли платформа пользователя ограниченные пространства отсчета.
Создание пространства отсчета
Запрос поддержки bounded-floor при вызове метода XRSystem requestSession() недостаточно для получения ограниченного пространства. Вам нужно запросить его при вызове 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().
См. также
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API/Bounded_reference_spaces