reckfellENGINE

Телефонный VR: MobileVRInterface

Проверенный lifecycle helper, параметры линз, единицы и ограничения телефонного stereo.

На этой странице

Телефонный VR: MobileVRInterface

MobileVRInterface — встроенный интерфейс для stereo-вывода на экран телефона в держателе. Имя в XRServer — Native mobile. Это отдельный путь от OpenXR и ARCore. Он моделирует поворот головы по доступным данным датчиков, а положение задаёт фиксированной высотой EyeHeight: ходьбу по комнате не отслеживает.

Если целевое устройство работает через OpenXR, используйте руководство запуска OpenXR. Этот раздел нужен для простого телефонного stereo-пути и диагностики его жизненного цикла.

Что означает успешный запуск

Initialize создаёт tracker head, делает интерфейс primary и возвращает true. В текущей реализации это происходит и без физического телефона. Поэтому сообщение «гарнитура подключена» после одного Initialize неверно. Два вида, наличие head pose и её фиксированная высота также не доказывают наличие датчиков или точность tracking.

Для вывода нужен Viewport с UseXR=true и XR-риг. Успешный запуск интерфейса не включает этот флаг автоматически. Не запускайте одновременно два компонента, управляющих primary interface и tracker head.

Пример с одним владельцем

Helper использует зарегистрированный интерфейс, отказывается перезаписывать существующий head/primary, сохраняет UseXR и освобождает только собственный запуск:

C#
using System;
using Reckfell;

public sealed class MobileVrPreview
{
    private MobileVRInterface? current;
    private XRTracker? head;
    private Viewport? viewport;
    private bool previousUseXr;

    // One owner, main thread. Call TryStop before leaving the preview.
    public bool TryStart(Viewport target)
    {
        ArgumentNullException.ThrowIfNull(target);
        if (current != null) return false;
        var candidate = XRServer.FindInterface("Native mobile") as MobileVRInterface;
        if (candidate == null || candidate.IsInitialized()
            || XRServer.PrimaryInterface != null || XRServer.GetTracker("head") != null)
            return false;
        bool oldUseXr = target.UseXR;
        if (!candidate.Initialize()) return false;
        var tracker = XRServer.GetTracker("head");
        if (tracker == null)
        {
            candidate.Uninitialize();
            return false;
        }
        current = candidate;
        head = tracker;
        viewport = target;
        previousUseXr = oldUseXr;
        target.UseXR = true;
        return true;
    }

    public bool TryStop()
    {
        var active = current;
        if (active == null) return true;
        // Do not unregister another provider's head tracker after a conflict.
        if (XRServer.PrimaryInterface != active || XRServer.GetTracker("head") != head)
            return false;
        if (viewport != null && ReckfellObject.IsInstanceValid(viewport))
            viewport.UseXR = previousUseXr;
        active.Uninitialize();
        current = null;
        head = null;
        viewport = null;
        return true;
    }
}

Сохраните один экземпляр MobileVrPreview в управляющем Entity. В _Ready передайте TryStart свой живой GetViewport(); проверяйте bool. При выходе из preview, до удаления владельца, вызовите TryStop. Для сообщений используйте ReckfellApi.Print, а не старый GD.Print.

TryStop=false означает конфликт владения: другой компонент изменил primary или head. Helper в этом случае не удаляет чужой tracker. Разрешите конфликт в управляющей логике; не продолжайте запуск второго XR-провайдера поверх первого. Повторный TryStop после успешной остановки безопасен.

Интерфейс и tracker заимствованы у XRServer. Не вызывайте у них Dispose/Free. Helper также не освобождает Viewport. Он не меняет параметры линз, глобальный WorldScale или reference frame: настройте их отдельно до старта.

Параметры и единицы

Параметр C#По умолчаниюСмысл
EyeHeight1.85Предполагаемая высота в метрах до применения WorldScale, не измерение положения телефона.
Iod6.0Межзрачковое расстояние в сантиметрах. При WorldScale=1 смещения глаз равны −0.03 и +0.03.
DisplayWidth14.5Физическая ширина экрана в сантиметрах, не разрешение в пикселях.
DisplayToLens4.0Расстояние от дисплея до линз в сантиметрах.
Oversample1.5Множитель размеров render target, влияющий также на расчёт frustum; не MSAA.
K1, K20.215, 0.215Безразмерные коэффициенты lens distortion, не универсальная калибровка всех держателей.
OffsetRect(0, 0, 1, 1)Область вывода относительно полного экранного прямоугольника.
VrsMinRadius20Центральная область полной плотности в процентах размера, если используется VRS. Допустимый диапазон setter: 1–100.
VrsStrength1Сила построения VRS-карты, диапазон 0.1–10. Не гарантия экономии GPU.

Измеряйте реальные параметры экрана и держателя. Не передавайте метры в DisplayToLens/Iod и сантиметры в EyeHeight. Для оптической модели нужны осмысленные положительные размеры. Setter многих параметров сохраняет число без проверки физической корректности.

Автоматическое чтение QR-профиля держателя в этом пути не реализовано: коэффициенты и размеры не подбираются по одному Initialize. Увеличение Oversample не исправляет ошибочную геометрию линз. В коде размер target на глаз рассчитывается как половина ширины окна × Oversample и высота окна × Oversample; большее значение увеличивает объём рендеринга.

Масштаб и кэш глаз

Задавайте WorldScale до запуска. В текущей реализации GetCameraOffsets кэширует смещения глаз. В выполненной проверке после смены WorldScale с 1 на 2 уже вычисленные ±0.03 остались прежними. После контролируемого TryStop/TryStart они стали ±0.06. Это воспроизведённое ограничение текущего движка, а не исправленная ошибка.

Изменение Iod на другое значение очищает кэш offsets и projections; DisplayWidth, DisplayToLens и Oversample очищают projections. Повторная запись того же значения не является универсальным сбросом. Getter массивов может возвращать общий кэш: не редактируйте его элементы для изменения настроек.

Датчики и вывод

Для Android исходник описывает настройки input_devices/sensors/enable_accelerometer, enable_gravity, enable_gyroscope и enable_magnetometer. Это включение источников ввода, а не доказательство наличия оборудования. Проверьте реальные значения и поведение на целевом устройстве. Состояние GetTrackingStatus и качество sensor fusion этим прогоном не приняты.

Основной путь вывода делит экран на левую и правую половины с lens distortion. Для SubViewport без экранного прямоугольника интерфейс не выводит изображение на экран и предупреждает об этом: отдельный render target сам по себе не становится изображением в держателе. VRS требует подходящего RD-рендерера и Viewport.VrsMode=Xr; свойства VRS не означают, что карта реально используется.

Пример C# проверен на Windows/SDK 1.0.0 как lifecycle-код. Это не подтверждение C#-экспорта на телефон. Поддержку платформы, языкового runtime и модулей нужно подтверждать используемой сборкой и тестом на устройстве.

Диагностика

СимптомПроверить
Native mobile не найденНаличие mobile_vr в сборке; модуль отключается при disable_xr.
TryStart возвращает falseУже запущенный интерфейс, занятые primary/head, повторный старт или отсутствие модуля.
Initialize успешен, голова неподвижнаДатчики и их настройки; успех инициализации не проверяет телефон.
Неверная высотаEyeHeight в метрах и WorldScale; это фиксированная модель высоты.
Изображение не сходитсяIod/DisplayWidth/DisplayToLens в сантиметрах, параметры держателя и distortion.
Смещения глаз не меняются с масштабомОстановите собственный preview и запустите после настройки масштаба; не перезаписывайте чужой head.
TryStop возвращает falseКонкурирующего владельца primary/head; helper специально не удаляет чужие данные.

Что проверено

Установленный Reckfell 1.0.0, Windows headless с XR off: 22 наблюдения по параметрам, старту/остановке helper, конфликтам владения, восстановлению UseXR, фиксированной высоте и расчётам двух видов. Для датчиков и изображения аппаратная приёмка не проводилась. Исходная проблема live-WorldScale кэша сохранена в отчёте как неуспешная приёмка.

Не проверены телефон, C#-экспорт на него, GetTrackingStatus initialization, точность датчиков, реальные линзы, stereo pixels, VRS output, комфорт и FPS. Исходники движка, установленный Runtime и SDK не менялись.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.