Используйте геопространственные привязки для позиционирования реального контента в Unity

Геопространственные привязки — это тип привязки , который позволяет размещать 3D-контент в реальном мире.

Типы геопространственных привязок

Существует три типа геопространственных привязок, каждый из которых обрабатывает высоту по-разному:

  1. Анкеры WGS84 :
    Якоря WGS84 позволяют размещать 3D-контент на любой заданной широте, долготе и высоте.

  2. Наземные анкеры :
    Якоря местности позволяют размещать контент, используя только широту и долготу с высотой относительно местности в этом месте. Высота определяется относительно земли или пола, как известно VPS .

  3. Анкеры на крыше :
    Якоря на крыше позволяют размещать контент, используя только широту и долготу с высотой относительно крыши здания в этом месте. Высота определяется относительно вершины здания, как это известно в Streetscape Geometry . По умолчанию это будет высота местности, если она не размещена на здании.

WGS84 Местность Крыша
Горизонтальная позиция Широта Долгота Широта Долгота Широта Долгота
Вертикальная позиция Относительно высоты WGS84 Относительно уровня местности, определенного Google Maps Относительно уровня крыши, определенного Google Maps
Требуется разрешение сервера? Нет Да Да

Предпосылки

Прежде чем продолжить, убедитесь, что вы включили Geospatial API .

Разместите геопространственные привязки

У каждого типа привязки есть специальные API для их создания; см. Типы геопространственных привязок для получения дополнительной информации.

Создайте якорь из хит-теста

Вы также можете создать геопространственную привязку на основе результатов проверки попадания . Используйте Pose из теста на попадание и преобразуйте его в GeospatialPose . Используйте его, чтобы разместить любой из трех описанных типов якоря.

Получите геопространственную позу из позы дополненной реальности

AREarthManager.Convert(Pose) предоставляет дополнительный способ определения широты и долготы путем преобразования позы AR в геопространственную позу.

Получите позу дополненной реальности из геопространственной позы

AREarthManager.Convert(GeospatialPose) преобразует указанное Земле горизонтальное положение, высоту и кватернионное вращение относительно системы координат восток-вверх-юг в положение AR относительно мировых координат GL.

Выберите, какой метод подходит для вашего варианта использования

Каждый метод создания якоря имеет связанные с ним компромиссы, о которых следует помнить:

  • При использовании Streetscape Geometry используйте тест на попадание, чтобы прикрепить контент к зданию.
  • Отдавайте предпочтение якорям Terrain или Rooftop, а не якорям WGS84, поскольку они используют значения высоты, определенные Google Maps.

Определить широту и долготу места

Широту и долготу местоположения можно рассчитать тремя способами:

  • Используйте Geospatial Creator для просмотра и дополнения мира 3D-контентом без необходимости физического перемещения в определенное место. Это позволяет визуально размещать иммерсивный 3D-контент с помощью карт Google в редакторе Unity. Широта, долгота, вращение и высота содержимого будут автоматически рассчитаны для вас.
  • Используйте карты Google
  • Используйте Google Планета Земля. Обратите внимание, что получение этих координат с помощью Google Earth, в отличие от Google Maps, даст вам погрешность до нескольких метров.
  • Перейти к физическому местоположению

Используйте карты Google

Чтобы получить широту и долготу местоположения с помощью Google Maps:

  1. Откройте Карты Google на настольном компьютере.

  2. Перейдите к Слои > Еще .

  3. Измените Тип карты на Спутник и снимите флажок «Обзор земного шара» в левом нижнем углу экрана.

    Это активирует 2D-перспективу и устранит возможные ошибки, которые могут возникнуть из-за углового 3D-вида.

  4. На карте щелкните правой кнопкой мыши местоположение и выберите долготу/широту, чтобы скопировать его в буфер обмена.

Используйте Google Планета Земля

Вы можете рассчитать широту и долготу местоположения из Google Планета Земля, щелкнув местоположение в пользовательском интерфейсе и прочитав данные из сведений о метке.

Чтобы получить широту и долготу местоположения с помощью Google Планета Земля:

  1. Перейдите в Google Планета Земля на настольном компьютере.

  2. Перейдите в меню гамбургеров и выберите Стиль карты .

  3. Выключите переключатель 3D-здания .

  4. После отключения переключателя 3D- зданий щелкните значок булавки. чтобы добавить метку в выбранное место.

  5. Укажите проект, который будет содержать вашу метку, и нажмите Сохранить .

  6. В поле Название метки введите имя метки.

  7. Щелкните стрелку назад на панели проекта и выберите Меню дополнительных действий .

  8. Выберите «Экспортировать как файл KML» в меню.

Файл KLM сообщает широту, долготу и высоту для метки в теге <coordinates> , разделенных запятыми, следующим образом:

<coordinates>-122.0755182435043,37.41347299422944,7.420342565583832</coordinates>

Не используйте широту и долготу из тегов <LookAt> , которые указывают положение камеры, а не местоположение.

Перейти к физическому местоположению

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

Получить кватернион вращения

GeospatialPose.EunRotation извлекает ориентацию из Geospatial Pose и выводит кватернион, который представляет собой матрицу вращения, преобразующую вектор из цели в систему координат восток-вверх-север (EUN). X+ указывает на восток, Y+ указывает вверх от гравитации, а Z+ указывает на север.

Анкеры WGS84

Якорь WGS84 — это тип якоря , который позволяет размещать 3D-контент на любой заданной широте, долготе и высоте. Он зависит от позы и ориентации для размещения в реальном мире. Позиция состоит из широты, долготы и высоты, которые указаны в системе координат WGS84 . Ориентация состоит из вращения кватерниона.

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

Разместите якорь WGS84 в реальном мире

Определить высоту места

Есть несколько способов определить высоту местоположения для размещения якорей:

  • Если местоположение привязки физически находится рядом с пользователем, вы можете использовать высоту, аналогичную высоте устройства пользователя.
  • Получив широту и долготу, используйте Elevation API , чтобы получить высоту на основе спецификации EGM96 . Вы должны преобразовать высоту Maps API EGM96 в WGS84 для сравнения с высотой GeospatialPose . См. GeoidEval , который имеет как командную строку, так и интерфейс HTML. Maps API сообщает широту и долготу в соответствии со спецификацией WGS84.
  • Широту, долготу и высоту местоположения можно получить из Google Планета Земля . Это даст вам погрешность до нескольких метров. Используйте широту, долготу и высоту из тегов <coordinates> , а не из тегов <LookAt> в файле KML.
  • Если существующий якорь находится рядом и если вы не находитесь на крутом склоне, вы можете использовать высоту из GeospatialPose камеры без использования другого источника, такого как Maps API.

Создайте якорь

Получив кватернион широты, долготы, высоты и вращения, используйте ARAnchorManagerExtensions.AddAnchor() для привязки содержимого к указанным вами географическим координатам.

if (earthTrackingState == TrackingState.Tracking)
{
  var anchor =
      AnchorManager.AddAnchor(
          latitude,
          longitude,
          altitude,
          quaternion);
  var anchoredAsset = Instantiate(GeospatialAssetPrefab, anchor.transform);
}

Анкеры рельефа

Якорь Terrain — это тип якоря , который позволяет вам размещать объекты AR, используя только широту и долготу, используя информацию от VPS для определения точной высоты над землей.

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

Установите режим поиска самолета

Поиск плоскости является необязательным и не требуется для использования якорей. Обратите внимание, что используются только горизонтальные плоскости. Горизонтальные плоскости помогут динамическому выравниванию якорей ландшафта на земле.

Обратите внимание, что на привязки рельефа влияют параметры Horizontal и Horizontal | Vertical

Используйте раскрывающееся меню Режим обнаружения , чтобы установить режим обнаружения:

Создайте якорь Terrain с помощью нового асинхронного API.

Чтобы создать и разместить привязку Terrain, вызовите ARAnchorManagerExtensions.resolveAnchorOnTerrainAsync() .

Якорь не будет готов сразу и нуждается в разрешении. После разрешения он будет доступен в ResolveAnchorOnTerrainPromise .

public GameObject TerrainAnchorPrefab;

public void Update()
{
    ResolveAnchorOnTerrainPromise terrainPromise =
        AnchorManager.ResolveAnchorOnTerrainAsync(
            latitude, longitude, altitudeAboveTerrain, eunRotation);

    // The anchor will need to be resolved.
    StartCoroutine(CheckTerrainPromise(terrainPromise));
}

private IEnumerator CheckTerrainPromise(ResolveAnchorOnTerrainPromise promise)
{
    yield return promise;

    var result = promise.Result;
    if (result.TerrainAnchorState == TerrainAnchorState.Success &&
        result.Anchor != null)
    {
        // resolving anchor succeeded
        GameObject anchorGO = Instantiate(TerrainAnchorPrefab,
            result.Anchor.gameObject.transform);
        anchorGO.transform.parent = result.Anchor.gameObject.transform;
    }
    else
    {
       // resolving anchor failed
    }

    yield break;
}

Проверьте состояние обещания

Промис будет иметь связанный PromiseState .

Состояние Описание
Pending Операция еще впереди.
Done Операция завершена, результат есть.
Cancelled Операция отменена.

Проверьте состояние привязки Terrain результата Promise.

TerrainAnchorState принадлежит асинхронной операции и является частью конечного результата Promise.

switch (result.TerrainAnchorState)
{
    case TerrainAnchorState.Success:
        // Anchor has successfully resolved
        break;
    case TerrainAnchorState.ErrorUnsupportedLocation:
        // The requested anchor is in a location that isn't supported by the Geospatial API.
        break;
    case TerrainAnchorState.ErrorNotAuthorized:
        // An error occurred while authorizing your app with the ARCore API. See
        // https://developers.google.com/ar/reference/unity-arf/namespace/Google/XR/ARCoreExtensions#terrainanchorstate_errornotauthorized
        // for troubleshooting steps.
        break;
    case TerrainAnchorState.ErrorInternal:
        // The Terrain anchor could not be resolved due to an internal error.
        break;
    default:
        break;
}

Анкеры на крыше

Анкеры для крыши Герой

Анкеры для крыши — это тип анкеров , очень похожий на анкеры Terrain, описанные выше. Разница в том, что вы укажете высоту над крышей, а не над землей.

Создайте якорь на крыше с помощью нового асинхронного API.

Якорь не будет готов сразу и нуждается в разрешении.

Чтобы создать и разместить привязку Rooftop, вызовите ARAnchorManagerExtensions.resolveAnchorOnRooftopAsync() . Как и в случае с привязками Terrain, вы также получите доступ к PromiseState объекта Promise. Затем вы можете проверить результат Promise, чтобы получить доступ к RooftopAnchorState .

public GameObject RooftopAnchorPrefab;

public void Update()
{
    ResolveAnchorOnRooftopPromise rooftopPromise =
        AnchorManager.ResolveAnchorOnRooftopAsync(
            latitude, longitude, altitudeAboveRooftop, eunRotation);

    // The anchor will need to be resolved.
    StartCoroutine(CheckRooftopPromise(rooftopPromise));
}

private IEnumerator CheckRooftopPromise(ResolveAnchorOnTerrainPromise promise)
{
    yield return promise;

    var result = promise.Result;
    if (result.RooftopAnchorState == RooftopAnchorState.Success &&
        result.Anchor != null)
    {
        // resolving anchor succeeded
        GameObject anchorGO = Instantiate(RooftopAnchorPrefab,
            result.Anchor.gameObject.transform);
        anchorGO.transform.parent = result.Anchor.gameObject.transform;
    }
    else
    {
       // resolving anchor failed
    }

    yield break;
}

Проверьте состояние обещания

Промис будет иметь связанный PromiseState , см. таблицу выше.

Проверьте состояние привязки Rooftop результата Promise.

RooftopAnchorState принадлежит асинхронной операции и является частью конечного результата Promise.

switch (result.RooftopAnchorState)
{
    case TerrainAnchorState.Success:
        // Anchor has successfully resolved
        break;
    case RooftopAnchorState.ErrorUnsupportedLocation:
        // The requested anchor is in a location that isn't supported by the Geospatial API.
        break;
    case RooftopAnchorState.ErrorNotAuthorized:
        // An error occurred while authorizing your app with the ARCore API. See
        // https://developers.google.com/ar/reference/unity-arf/namespace/Google/XR/ARCoreExtensions#terrainanchorstate_errornotauthorized
        // for troubleshooting steps.
        break;
    case RooftopAnchorState.ErrorInternal:
        // The Rooftop anchor could not be resolved due to an internal error.
        break;
    default:
        break;
}

Что дальше