Модели рендеринга OpenXR
Краеугольным камнем архитектуры API OpenXR является максимальная платформенная независимость. Прекрасным примером этого является система карт действий OpenXR, где среды выполнения XR должны поддерживать основные профили взаимодействия, к которым можно обратиться, если для используемого оборудования профиль взаимодействия отсутствует. Это гарантирует работоспособность приложений OpenXR даже при использовании на оборудовании, которого не существовало на момент выпуска приложения, или к которому у разработчиков приложения не было доступа.
Следствием этого является то, что разработчик приложения не может точно знать, какое оборудование используется, поскольку среда выполнения XR может имитировать другое оборудование. Таким образом, разработчик приложения не может показать ничего, связанного с фактически используемым оборудованием. Наиболее распространённый вариант использования — отображение контроллеров, которые в данный момент держит пользователь.
Демонстрация правильных моделей контроллеров и их правильное расположение важны для создания ощущения полного погружения.
Именно здесь на помощь приходит API рендеринга моделей OpenXR. Этот API позволяет нам запрашивать у среды выполнения XR 3D-ресурсы, соответствующие используемому физическому оборудованию. API также позволяет нам запрашивать положение этого оборудования в области отслеживания и корректное позиционирование его подкомпонентов.
Например, мы можем правильно расположить и анимировать триггер или показать нажатие кнопок.
В средах выполнения, поддерживающих источник данных контроллера для отслеживания рук, мы также можем корректно позиционировать пальцы и кисть пользователя в соответствии с формой контроллера. Обратите внимание, что это работает в сочетании с расширением диапазона движения суставов руки, чтобы предотвратить застревание пальцев.
Узел моделей рендеринга OpenXR
Узел OpenXRRenderModelManager можно использовать для автоматизации большинства функций рендеринга моделей. Этот узел отслеживает активные рендеринг-модели, доступные в данный момент в среде выполнения XR.
Он создаст дочерние узлы для каждой активной модели рендеринга, в результате чего будет отображена эта модель рендеринга.
Этот узел должен иметь узел XROrigin3D в качестве предка.
Если для tracker задано значение Any, наш узел будет отображать все отслеживаемые в данный момент модели рендеринга. В этом случае этот узел должен быть прямым дочерним узлом нашего узла XROrigin3D.
Если для tracker задано значение None set, наш узел будет отображать только модели рендеринга, для которых не идентифицирован трекер. В этом случае этот узел также должен быть прямым дочерним узлом нашего узла XROrigin3D.
Если tracker установлен на Left Hand или Right Hand, наш узел будет отображать только модели рендеринга, относящиеся к левой или правой руке соответственно. В этом случае наш узел можно разместить глубже в дереве сцены.
Предупреждение
Для большинства сред выполнения XR это означает, что модель рендеринга представляет собой контроллер, который фактически находится в руках пользователя, но это не гарантируется. Некоторые среды выполнения XR всегда устанавливают трекер либо на левую, либо на правую руку, даже если контроллер в данный момент не находится в руках, но отслеживается. Всегда проверяйте это, так как это может привести к нежелательному поведению.
В этом сценарии мы также можем указать действие для позы на карте действий, установив свойство make_local_to_pose для действия позы. Используйте это в сочетании с узлом XRController3D, который использует ту же позу, и теперь вы можете добавить слой, позволяющий отклоняться от отслеживаемого положения как вашего контроллера, так и связанной с ним модели рендеринга (см. пример ниже).
Примечание
Сочетание вышеперечисленного с отслеживанием рук приводит к проблеме, поскольку отслеживание рук полностью независимо от системы карт действий. Вам потребуется объединить отслеживание рук и позы отслеживания контроллера для правильного смещения моделей рендеринга.
Это выходит за рамки данной документации.
Пример менеджера моделей рендеринга
Вы можете загрузить нашу демонстрационную версию моделей рендеринга, которая реализует описанную ниже настройку.
В этой настройке мы находим узел OpenXRRenderModelManager непосредственно под нашим узлом XROrigin3D. В этом узле наше свойство target установлено в None set и будет обрабатывать отображение всех моделей рендеринга, которые в данный момент не связаны с нашими левым или правым контроллерами.
Затем мы видим ту же самую установку для левой и правой руки, поэтому сосредоточимся только на левой руке.
У нас есть XRController3D, который будет отслеживать местоположение нашей руки.
Примечание
В этом примере мы используем позу grip«хват». Поза palm «ладонь», возможно, более подходящая и предсказуемая, однако она поддерживается не всеми средами выполнения XR. Решение переключения между этими позами в зависимости от поддерживаемых конфигураций можно найти в демонстрационном проекте отслеживания рук.
В качестве дочернего элемента узла у нас есть узел AnimatableBody3D, который следует за отслеживаемым местоположением руки, но будет взаимодействовать с физическими объектами, чтобы не дать руке игрока пройти сквозь стены и т. д. Этот узел имеет форму столкновения, которая инкапсулирует руку.
Примечание
Важно установить приоритет физики так, чтобы эта логика выполнялась после любой физической логики, которая перемещает узел XROrigin3D, иначе рука будет отставать на кадр.
Приведенный ниже сценарий демонстрирует базовую реализацию этого решения, которую вы можете использовать в качестве основы.
class_name CollisionHands3D
extends AnimatableBody3D
func _ready():
# Make sure these are set correctly.
top_level = true
sync_to_physics = false
process_physics_priority = -90
func _physics_process(_delta):
# Follow our parent node around.
var dest_transform = get_parent().global_transform
# We just apply rotation for this example.
global_basis = dest_transform.basis
# Attempt to move to where our tracked hand is.
move_and_collide(dest_transform.origin - global_position)
Наконец, мы видим ещё один узел OpenXRRenderModelManager, в котором target соответствует соответствующей руке, а make_local_to_pose — правильной позе. Это гарантирует, что модели рендеринга, связанные с этой рукой, будут отображаться и смещаться, если наш обработчик столкновений изменит местоположение.
Узел модели рендеринга
Узел OpenXRRenderModel реализует всю логику для отображения и позиционирования заданной модели рендеринга, предоставляемой API моделей рендеринга.
Экземпляры этого узла добавляются узлом менеджера моделей рендеринга, который мы использовали выше, но при желании вы можете взаимодействовать с ними напрямую.
Всякий раз, когда Godot получает информацию о новой модели рендеринга, создается RID для ссылки на эту модель рендеринга.
Назначив этот RID свойству render_model этого узла, узел начнет отображать модель рендеринга и управлять как преобразованием, которое помещает модель рендеринга в правильное место, так и анимацией всех подобъектов.
Функция get_top_level_path вернет путь верхнего уровня, связанный с этой моделью рендеринга. Он будет указывать либо на левую, либо на правую руку. Поскольку путь верхнего уровня может быть установлен или удален в зависимости от того, поднимает ли пользователь контроллер или опускает его, вы можете подключиться к сигналу render_model_top_level_path_changes и реагировать на эти изменения.
В зависимости от настройки узлов OpenXRRenderModelManager, модели рендеринга будут удаляться или добавляться по мере изменения их пути верхнего уровня.
Внутренний доступ
Узлы, которые мы подробно описали выше, обрабатывают всю логику отображения, но можно напрямую взаимодействовать с данными, которые этим управляют, и создавать собственную реализацию.
Для этого можно обратиться к синглтону OpenXRRenderModelExtension.
Этот объект также позволяет вам запрашивать, поддерживаются ли и включены ли модели рендеринга на текущем устройстве, вызывая функцию is_active для этого объекта.
Встроенная логика реализует API модели рендеринга взаимодействия, который выводит список всех моделей рендеринга, связанных с контроллерами и аналогичными устройствами, представленными на карте действий. Он автоматически создает и удаляет сущности моделей рендеринга, доступные через этот API.
По мере появления других расширений их можно будет реализовать в плагине GDExtension. Такой плагин может вызывать render_model_create и render_model_destroy для создания объекта, который обеспечит доступ к этой модели рендеринга через API базовых моделей рендеринга.
Не следует уничтожать модель рендеринга вне этой логики.
Вы можете подключиться к сигналам render_model_added и render_model_removed, чтобы получать уведомления о добавлении или удалении новых моделей рендеринга.
Основные методы работы с этим API перечислены ниже:
Функция |
Описание |
|---|---|
render_model_get_all |
Предоставляет массив RID-ов для всех отслеживаемых моделей рендеринга. |
render_model_new_scene_instance |
Предоставляет новую сцену, содержащую все сетки, необходимые для отображения модели рендеринга. |
render_model_get_subaction_paths |
Предоставляет список путей поддействий из вашей карты действий, связанных с этим режимом рендеринга. |
render_model_get_top_level_path |
Возвращает путь верхнего уровня, связанный с этой моделью рендеринга (если таковой имеется). Используйте сигнал |
render_model_get_confidence |
Возвращает достоверность отслеживания для данных отслеживания для этой модели рендеринга. |
render_model_get_root_transform |
Возвращает корневое преобразование для данной модели рендеринга в текущем пространстве отсчета. Это преобразование можно использовать для размещения модели рендеринга в пространстве. |
render_model_get_animatable_node_count |
Возвращает количество узлов в нашей сцене модели рендеринга, которые можно анимировать |
render_model_get_animatable_node_name |
Возвращает имя узла, который можно анимировать. Обратите внимание, что этот узел может находиться на любом количестве уровней в глубину сцены. |
render_model_is_animatable_node_visible |
Возвращает true, если этот анимируемый узел должен быть видимым |
render_model_get_animatable_node_transform |
Возвращает преобразование для данного анимируемого узла. Это локальное преобразование, которое можно применить напрямую. |