Используйте геопрос��ранственные привязки для позиционирования реального контента на 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;
}

Что дальше