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

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

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

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

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

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

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

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

Предварительные условия

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  2. Перейдите в «Слои» > «Еще» .

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

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

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

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

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

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

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

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

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

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

  5. Укажите проект, в котором будет храниться метка, и нажмите «Сохранить» .

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

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

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

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

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

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

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

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

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

ArGeospatialPose_getEastUpSouthQuaternion() извлекает ориентацию из геопространственной позы и выводит кватернион, который представляет матрицу вращения, преобразующую вектор из цели в систему координат восток-вверх-юг (EUS). X+ указывает на восток, Y+ указывает вверх, а Z+ указывает на юг. Значения записываются в порядке {x, y, z, w} .

Якоря WGS84

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

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

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

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

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

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

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

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

float eus_quaternion_4[4] = {qx, qy, qz, qw};
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArAnchor* earth_anchor = NULL;
    ArStatus status = ArEarth_acquireNewAnchor(ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude,
        eus_quaternion_4, &earth_anchor);

    // Attach content to the anchor specified by geodetic location and
    // pose.
  }
}

Якоря местности

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

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

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

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

Используйте ArPlaneFindingMode , чтобы выбрать, как ваше приложение будет обнаруживать самолеты.

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

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

Якорь не будет готов сразу и его необходимо разрешить. Как только проблема будет решена, она будет доступна в ArResolveAnchorOnTerrainFuture .

Проверьте состояние привязки ландшафта, используя ArResolveAnchorOnTerrainFuture_getResultTerrainAnchorState() . Получите разрешенный якорь, используя ArResolveAnchorOnTerrainFuture_acquireResultAnchor() .

float eus_quaternion_4[4] = {qx, qy, qz, qw};
void* context = NULL;
ArResolveAnchorOnTerrainCallback callback = NULL;
ArResolveAnchorOnTerrainFuture* future = NULL;
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArStatus status = ArEarth_resolveAnchorOnTerrainAsync(
        ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude_above_terrain, eus_quaternion_4,
        context, callback, &future);
  }
}

Проверьте состояние будущего

Будущее будет иметь связанный ArFutureState .

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

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

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

switch (terrain_anchor_state) {
  case AR_TERRAIN_ANCHOR_STATE_SUCCESS:
    // A resolving task for this anchor has been successfully resolved.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_UNSUPPORTED_LOCATION:
    // The requested anchor is in a location that isn't supported by the
    // Geospatial API.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_NOT_AUTHORIZED:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/c/group/ar-anchor#:~:text=from%20this%20error.-,AR_TERRAIN_ANCHOR_STATE_ERROR_NOT_AUTHORIZED,-The%20authorization%20provided
    // for troubleshooting steps.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_INTERNAL:
    // The Terrain anchor could not be resolved due to an internal error.
    break;
  default:
    break;
}

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

Анкеры для крыши Hero

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

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

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

Чтобы создать и разместить якорь на крыше, вызовите ArEarth_resolveAnchorOnRooftopAsync() . Как и в случае с якорями Terrain, вы также получите доступ к ArFutureState of the Future. Затем вы можете проверить результат Future, чтобы получить доступ к ArRooftopAnchorState .

Используйте ArEarth_resolveAnchorOnRooftopAsync() , чтобы создать ArResolveAnchorOnRooftopFuture .

Проверьте состояние якоря на крыше, используя ArResolveAnchorOnRooftopFuture_getResultRooftopAnchorState() .

Получите разрешенный якорь, используя ArResolveAnchorOnRooftopFuture_acquireResultAnchor() .

float eus_quaternion_4[4] = {qx, qy, qz, qw};
void* context = NULL;
ArResolveAnchorOnRooftopCallback callback = NULL;
ArResolveAnchorOnRooftopFuture* future = NULL;
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArStatus status = ArEarth_resolveAnchorOnRooftopAsync(
        ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude_above_rooftop, eus_quaternion_4,
        context, callback, &future);
  }
}

Проверьте состояние будущего

Future будет иметь связанный ArFutureState , см. таблицу выше.

Проверьте состояние привязки на крыше результата Future.

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

switch (rooftop_anchor_state) {
  case AR_ROOFTOP_ANCHOR_STATE_SUCCESS:
    // A resolving task for this anchor has been successfully resolved.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_UNSUPPORTED_LOCATION:
    // The requested anchor is in a location that isn't supported by the
    // Geospatial API.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_NOT_AUTHORIZED:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/c/group/ar-anchor#:~:text=from%20this%20error.-,AR_ROOFTOP_ANCHOR_STATE_ERROR_NOT_AUTHORIZED,-The%20authorization%20provided
    // for troubleshooting steps.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_INTERNAL:
    // The Rooftop anchor could not be resolved due to an internal error.
    break;
  default:
    break;
}

Что дальше