Spec-Zone.ru › Web APIs

Пространства и пространства отсчёта: пространственное отслеживание в WebXR

API WebXR, используемые для реализации дополненной и виртуальной реальности, разработаны специально для возможности встраивания пользователя в виртуальную среду. Для этого программному обеспечению необходима способность не только отслеживать местоположение, ориентацию и перемещения объектов в виртуальном мире, но и местоположение, ориентацию и перемещение пользователя. Но WebXR идёт дальше, добавляя возможность отслеживать местоположение, ориентацию и движения входных устройств, которые генерируют данные, используемые для определения положения и движения отдельных частей тела зрителя (при соответствующем оборудовании).

Местоположение и перемещение шлема пользователя представляют положение и ориентацию его головы в виртуальной среде. Контроллеры для рук представляют его руки аналогичным образом. Другие аппаратные элементы могут аналогичным образом использоваться для представления других частей тела, предоставляя дополнительные данные для использования при моделировании действий пользователя в его среде.

В этом руководстве мы рассмотрим, как WebXR использует пространства и, более конкретно, пространства отсчёта, для отслеживания положений, ориентаций и движений объектов и тела пользователя в виртуальном мире.

Примечание: Эта статья предполагает, что вы знакомы с понятиями, представленными в Геометрия и пространства отсчёта в WebXR: это основы 3D систем координат, а также пространства WebXR, пространства отсчёта и способы использования пространств отсчёта для создания локальных систем координат для отдельных объектов или подвижных компонентов в сцене.

Представление позиции с использованием пространства отсчёта

Как описано в Определение пространственных отношений с пространствами отсчёта, пространства отсчёта устанавливают локальную систему координат, смещённую относительно другой системы координат, которая сама определяется каким-либо другим пространством. Таким образом, пространство отсчёта может использоваться для определения положения и ориентации точки и, по расширению, всего объекта, для которого эта точка является началом отсчёта. Хотя это немного избыточно для каждого отдельного объекта в сцене, это может быть очень полезно для нескольких конкретных объектов, чтобы иметь свою собственную систему координат таким образом.

  • Пространство мира; начало этого пространства является началом системы координат WebGL, лежащей в основе всего 3D холста.
  • Игрок, аватар или камера; начало этого пространства используется как позиция камеры для рендеринга сцены, которая будет отображаться пользователю.
  • Рука и/или контроллер для руки; каждый из них представляет одну из рук пользователя, либо в виде самой руки, либо контроллера (или того и другого). Началом обычно является центр кулака руки пользователя.
  • Луч цели; каждый контроллер или другое ручное устройство может иметь связанный с ним луч цели, который представляется пространством, начало которого находится в точке контроллера, из которой испускается луч, а ориентация такова, что -Z направлен в направлении цели, на которую он нацелен.

Поскольку каждый из них определён с использованием пространства отсчёта в качестве основы, API устройства WebXR может легко использоваться для преобразования между системами координат, выполнения операций, влияющих на эти пространства и соответствующие объекты, и так далее.

Описание позиции относительно пространства

Существуют две ситуации, в которых вам может потребоваться описать положение и/или ориентацию относительно пространства. Первая — описана выше: применение пространства отсчёта к смещению (или наоборот, поскольку результат одинаков) для определения матрицы преобразования, которая представляет результирующее расположение в системе координат пространства.

Позы

После того, как вы установили пространства отсчёта или пространства отсчёта для различных ключевых объектов в сцене, у вас могут возникнуть ситуации, когда вам нужно описать другую позицию относительно начала определённого пространства отсчёта. Это делается с помощью поз. Поза, в свою очередь, описывает положение и ориентацию относительно начала пространства отсчёта, из которого она была создана.

В WebXR поза представлена объектом XRPose, свойство transform которого является объектом XRRigidTransform, определяющим матрицу преобразования, которая, применённая к любой координате, вектору или матрице в исходном пространстве, преобразует её в целевое пространство. Таким образом, с помощью позы можно не только преобразовывать и определять положения, но и получать информацию о вращении.

Существует только один способ создания XRPose, и это использование метода getPose() на кадре анимации, как предоставлено с помощью объекта XRFrame. Это означает, что чаще всего вы будете использовать позы в коде рендеринга кадра, который выполняется как обратный вызов от метода XRFrame requestAnimationFrame().

getPose() вычисляет положение XRReferenceSpace относительно начала указанного XRSpace и затем создаёт позу, представляющую результирующее положение и ориентацию.

Например, если вы хотите нарисовать представление контроллера для руки, используя gripSpace контроллера, вы можете получить необходимую позу так:

let controlPose = frame.getPose(inputSource.gripSpace, worldRefSpace);

Это преобразует положение и ориентацию пространства захвата ввода в использование системы координат мира, затем генерирует соответствующую XRPose, сохраняя её в controlPose. Затем вы можете применить transform controlPose к вершинам в модели объекта, представляющей контроллер, чтобы рассчитать координаты WebGL, используемые при рендеринге представления контроллера в буфер кадра.

Позы наблюдателя

Специализированный тип позы, поза наблюдателя, представляет перспективу наблюдателя сцены. Поза наблюдателя представлена интерфейсом XRViewerPose WebXR. При рендеринге кадра вы используете позу наблюдателя, чтобы определить положение и направление взгляда наблюдателя, чтобы разместить виртуальную камеру и отрендерить сцену.

Единственный способ получить позу, которая адаптирует пространственную информацию из одного пространства в другое, — через объект XRFrame, полученный функцией обратного вызова рендеринга кадра, указанной при вызове метода XRSession requestAnimationFrame().

Например, если у вас есть XRSession, пространство отсчёта которого равно worldRefSpace, следующая строка кода запросит планирование первого кадра анимации:

animationFrameRequestID = xrSession.requestAnimationFrame(myDrawFrame);

Затем функция myDrawFrame(), обратный вызов, выполняемый, когда пришло время нарисовать кадр, может выглядеть примерно так:

function myDrawFrame(currentFrameTime, frame) {
  let session = frame.session;
  let viewerPose = frame.getViewerPose(viewerRefSpace);

  animationFrameRequestID = session.requestAnimationFrame(myDrawFrame);

  if (viewerPose) {
    // render the frame
  }
}

Параметр frame — это XRFrame, представляющий информацию о кадре анимации, предоставленную WebXR. При вызове эта функция начинает с получения XRSession из объекта кадра, а затем использует метод getViewerPose() кадра для вычисления XRViewerPose для наблюдателя, учитывая viewerRefSpace, который описывает текущее направление взгляда и положение наблюдателя.

Возвращённая поза наблюдателя, viewerPose, в свою очередь, может использоваться для вычисления положений и ориентаций для правильного рендеринга объектов в сцене с точки зрения пользователя.

Смещение или перемещение пространств отсчёта

Хотя вы не можете изменить пространство отсчёта, поскольку как XRReferenceSpace, так и XRBoundedReferenceSpace являются только для чтения, вы можете легко создать новые пространства отсчёта, применяя к ним преобразование смещения. Это делается с помощью метода getOffsetReferenceSpace() пространства отсчёта.

Смещение позиций в пространстве отсчёта

Простейший случай использования getOffsetReferenceSpace() — это преобразование точки или матрицы в контексте того же пространства. Например, чтобы создать новое пространство отсчёта, перемещающее пространство отсчёта aRefSpace на полметра в каждом направлении, вы можете сделать следующее:

let halfMeterTransform = new XRRigidTransform({
  x: 0.5,
  y: 0.5,
  z: 0.5,
  w: 1.0,
});
aRefSpace = aRefSpace.getOffsetReferenceSpace(halfMeterTransform);

Это заменяет существующее пространство отсчёта aRefSpace пространством, координаты и ориентация которого подверглись применению преобразования halfMeterTransform. Без включения данных об ориентации в преобразование ориентация aRefSpace не изменяется.

Преобразование между типами сессий WebXR

Ещё одна распространённая причина, по которой вам может потребоваться преобразовать информацию о местоположении из одного пространства отсчёта в другое, — это необходимость изменения типа сессии с inline на immersive-vr или обратно. Это часто происходит, когда ваш пользовательский интерфейс предоставляет способ предварительного просмотра сцены непосредственно в контексте веб-страницы с кнопкой или другим элементом управления для переключения в интерактивный режим.

Поскольку большинство пользователей предпочитают, чтобы вы сохранили то же положение и направление взгляда наблюдателя при выполнении этого перехода, вы можете использовать метод XRFrame getViewerPose() для получения текущей XRViewerPose, переключить сессию, а затем использовать сохранённую позу наблюдателя для восстановления положения и направления взгляда наблюдателя.

let viewerPose = frame.getViewerPose(worldReferenceSpace);
let newSession = navigator.xr.requestSession("immersive-vr", {
  requiredFeatures: "unbounded",
});
worldReferenceSpace = await newSession.requestReferenceSpace("unbounded");
viewerPose = worldReferenceSpace.getOffsetReferenceSpace(viewerPose.transform);

Здесь поза наблюдателя получена, и её преобразование определено относительно worldReferenceSpace, глобального пространства отсчёта текущей сессии. Затем создаётся новая сессия и пространство отсчёта, которое станет новым пространством отсчёта мира.

Наконец, сохранённая viewerPose преобразуется в систему координат нового пространства мира с помощью метода getOffsetReferenceSpace() новой системы отсчёта. Имея это, мы можем продолжить рендеринг сцены как обычно, без изменения перспективы наблюдателя.

END_OF_DOCUMENT_MARKER

Преобразование между ограниченными и неограниченными пространствами

Иногда, когда основное взаимодействие происходит в неограниченном пространстве, может потребоваться временно переключить опыт пользователя на ограниченное пространство. Например, взаимодействие с объектами в одной комнате дома может быть проще реализовано, переключившись на ограниченное пространство, представляющее эту комнату. Это может упростить такие задачи, как реализация поддержки настройки стен, размещения мебели на полу и т. д.

В таких случаях, когда вам нужно начать отслеживание с использованием другого пространства отсчета, отличного от того, которое вы использовали ранее, вы можете использовать комбинацию getViewerPose() и некоторых матричных вычислений, чтобы перевести все в вашей сцене в новую систему отсчета.

Поскольку getViewerPose() доступна только в XRFrame, вам необходимо начать этот процесс в обратном вызове рендеринга, возможно, используя рабочую нить для вычислений, чтобы уменьшить пропуски кадров.

let previousViewerPose = null;

function myDrawFrame(currentFrameTime, frame) {
  let session = frame.session;
  let viewerPose = frame.getViewerPose(viewerRefSpace);

  animationFrameRequestID = session.requestAnimationFrame(myDrawFrame);

  if (viewerPose) {
    if (!previousViewerPose) {
      previousViewerPose = viewerPose;
    }

    let offsetMatrix = mat4.create();
    mat4.sub(
      offsetMatrix,
      previousViewerPose.transform.matrix,
      viewerPose.transform.matrix,
    );

    previousViewerPose = viewerPose;
  }
}

Непрерывность и восстановление после потери отслеживания

Иногда, пока пользователь активно использует свою XR-аппаратуру с вашим приложением, поток данных, содержащий обновления о позиции и ориентации пользователя, может быть потерян на некоторое время. Ваше приложение не только должно определить, что показывать пользователю во время этих периодов, но и должно корректно восстановиться при возобновлении отслеживания.

Как только XR-аппаратура начнет предоставлять информацию об отслеживании, она будет продолжать это делать до тех пор, пока сессия XR не будет закрыта. Эти данные получаются в каждом кадре путем вызова метода XRFrame getViewerPose() для получения позиции и направления взгляда зрителя (определяя, что должен видеть пользователь) и getPose() для получения любых других поз, таких как положение контроллеров рук и других частей XR-системы.

Обнаружение и функционирование после потери отслеживания

Если отслеживание завершается неудачно, например, из-за временной потери соединения между шлемом и устройством пользователя, XR-слой будет продолжать возвращать позы, но свойство emulatedPosition этих поз будет true, указывая, что вычисление позы основано на предположении о текущем положении пользователя.

Некоторые XR-устройства используют алгоритмы для вычисления предполагаемой позиции пользователя, основанной на текущем движении, в то время как другие устройства вообще не будут сообщать о движении, но с emulatedPosition установленным в true. В любом случае, вы можете захотеть скорректировать рендеринг, чтобы компенсировать потерю, в зависимости от ваших конкретных потребностей.

Когда отслеживание возобновляется

Вы можете обнаружить возобновление отслеживания после его потери, когда позиция пользователя меняется скачком, а значение emulatedPosition меняется с true на false. Как вы обработаете это, зависит от вашего приложения. Если ваше приложение предоставляет способ перемещения пользователя по виртуальному миру без физического перемещения в реальном мире (так называемый механизм телепортации), вы можете принять новую позицию и продолжить, позволив мгновенно скорректировать скачок с вашей предыдущей предполагаемой позиции до новой позиции.

С другой стороны, если ваше приложение подразумевает физическое перемещение пользователя в реальном пространстве для перемещения по виртуальному миру, принятие новой позиции отслеживания и переход туда могут быть неудобны для пользователя и должны быть избегаемы, если это возможно. Вместо этого используйте разницу между текущей позицией и новой позицией отслеживания для вычисления нового смещения телепортации, то есть преобразования, применяемого ко всему, чтобы адаптировать данные о позиции и ориентации из WebXR к вашим потребностям.

Вы можете сделать это, создав новое пространство отсчета, которое включает в свой эффективный центр расстояние, на которое прыгнула позиция зрителя с предыдущего кадра, используя метод XRReferenceSpace getOffsetReferenceSpace().

Событие сброса

<<<--- этот раздел, вероятно, все еще имеет проблемы; приветствуются исправления --->>>

При возникновении разрыва или прерывания в родном или эффективном начале пространства отсчета пользовательский агент отправит агенту XRReferenceSpace событие reset. Это событие указывает на то, что произошло значительное изменение позиции начала относительно среды пользователя.

Возникновение reset может произойти потому, что XR-аппаратура потеряла соединение на некоторое время, что привело к тому, что перемещения пользователя некоторое время не отслеживались должным образом. При восстановлении отслеживания reset означает, что отслеживание восстановлено, а новая информация о позиции представляет фактическую информацию о позиции, предоставленную XR-аппаратурой, а не кэшированные или "наилучшие" данные.

Другая причина, по которой reset может быть отправлена, заключается в том, что пользователь вышел за пределы пространства отсчета и вошел в другое пространство отсчета, или потому, что пользователь был программно переведен из одного пространства отсчета в другое. Всякий раз, когда изменяется геометрия границ пространства пользователя, отправляется reset.

reset используется только для значительных скачков или переходов; незначительные изменения просто автоматически поглощаются. Событие всегда отправляется каждому затронутому пространству отсчета, включая те, которые созданы с помощью getOffsetReferenceSpace(), поэтому, если вы прослушиваете события reset, вам нужно убедиться, что вы сохраняете сильную ссылку на все используемые вами пространства.

См. также

  • Матричная математика для веб-приложений
  • Геометрия и пространства отсчета в WebXR
  • Рендеринг и обратный вызов анимации кадра WebXR
  • Точки обзора и зрители: моделирование камер в WebXR
  • Перемещение, ориентация и движение: пример WebXR
  • Использование ограниченных пространств отсчета

© 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/Spatial_tracking

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API