Przewodnik dla programistów dotyczący błyskawicznych miejsc docelowych dla pakietu Android NDK

Dowiedz się, jak korzystać z interfejsu Instant Placement API. we własnych aplikacjach.

Wymagania wstępne

Upewnij się, że znasz podstawowe pojęcia związane z AR. i dowiedz się, jak skonfigurować sesję ARCore, zanim przejdziesz dalej.

Konfigurowanie nowej sesji z użyciem Szybkiego miejsca docelowego

W nowej sesji ARCore włącz tryb błyskawicznego miejsca docelowego.

// Create a session config.
ArConfig* ar_config = NULL;
ArConfig_create(ar_session, &ar_config);

// Enable Instant Placement mode.
ArConfig_setInstantPlacementMode(ar_session, ar_config,
                                 AR_INSTANT_PLACEMENT_MODE_LOCAL_Y_UP);
CHECK(ArSession_configure(ar_session, ar_config) == AR_SUCCESS);

// Release config resources.
ArConfig_destroy(ar_config);

Umieszczanie obiektu

W nowej sesji ARCore przeprowadź test trafienia dynamicznego miejsca docelowego, używając ArFrame_hitTestInstantPlacement Następnie utwórz nowy plik ArAnchor za pomocą Pozycja ArInstantPlacementPoint z ARTrackable wyniku działania.

ArFrame* ar_frame = NULL;
if (ArSession_update(ar_session, ar_frame) != AR_SUCCESS) {
  // Get the latest frame.
  LOGE("ArSession_update error");
  return;
}

// Place an object on tap.
// Use the estimated distance from the user's device to the closest
// available surface, based on expected user interaction and behavior.
float approximate_distance_meters = 2.0f;

ArHitResultList* hit_result_list = NULL;
ArHitResultList_create(ar_session, &hit_result_list);
CHECK(hit_result_list);

// Returns a single result if the hit test was successful.
ArFrame_hitTestInstantPlacement(ar_session, ar_frame, x, y,
                                approximate_distance_meters, hit_result_list);

int32_t hit_result_list_size = 0;
ArHitResultList_getSize(ar_session, hit_result_list, &hit_result_list_size);
if (hit_result_list_size > 0) {
  ArHitResult* ar_hit_result = NULL;
  ArHitResult_create(ar_session, &ar_hit_result);
  CHECK(ar_hit_result);
  ArHitResultList_getItem(ar_session, hit_result_list, 0, ar_hit_result);
  if (ar_hit_result == NULL) {
    LOGE("ArHitResultList_getItem error");
    return;
  }

  ArTrackable* ar_trackable = NULL;
  ArHitResult_acquireTrackable(ar_session, ar_hit_result, &ar_trackable);
  if (ar_trackable == NULL) {
    LOGE("ArHitResultList_acquireTrackable error");
    return;
  }
  ArTrackableType ar_trackable_type = AR_TRACKABLE_NOT_VALID;
  ArTrackable_getType(ar_session, ar_trackable, &ar_trackable_type);

  if (ar_trackable_type == AR_TRACKABLE_INSTANT_PLACEMENT_POINT) {
    ArInstantPlacementPoint* point = (ArInstantPlacementPoint*)ar_trackable;

    // Gets the pose of the Instant Placement point.
    ArPose* ar_pose = NULL;
    ArPose_create(ar_session, NULL, &ar_pose);
    CHECK(ar_pose);
    ArInstantPlacementPoint_getPose(ar_session, point, ar_pose);

    // Attaches an anchor to the Instant Placement point.
    ArAnchor* anchor = NULL;
    ArStatus status = ArTrackable_acquireNewAnchor(ar_session, ar_trackable,
                                                   ar_pose, &anchor);
    ArPose_destroy(ar_pose);
    // Render content at the anchor.
    // ...
  }

  ArTrackable_release(ar_trackable);
}

Obsługa błyskawicznych miejsc docelowych śledzenie przestrzeni ekranu z przybliżoną odległością, automatyczne przełączenie na pełne śledzenie, gdy punkt Błyskawicznego miejsca docelowego w świecie rzeczywistym. Uzyskaj bieżącą pozycję dzięki ArInstantPlacementPoint_getPose() Pobierz aktualną metodę śledzenia za pomocą ArInstantPlacementPoint_getTrackingMethod()

Chociaż ARCore może przeprowadzać testy trafień błyskawicznego miejsca docelowego na w orientacji strony, wyniki działań zawsze zwracają pozę ze znakiem +Y w górę, kierunku grawitacji. Na platformach poziomych testy trafień zwracają dokładne może pojawiać się znacznie szybciej.

Monitorowanie metody śledzenia punktów miejsc docelowych w dynamicznym miejscu docelowym

Jeśli ARCore ma dokładną pozycję 3D dla urządzenia ArInstantPlacementPoint zwróconego przez ArFrame_hitTestInstantPlacement, zaczyna się od metody śledzenia. AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING. W przeciwnym razie zacznie się od metody śledzenia AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE. i przejście na AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING gdy ARCore uzyska dokładną pozycję 3D. Gdy metoda śledzenia AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING – nie zostanie cofnięta do AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE

Płynniejsze przejście między metodami śledzenia

Gdy metoda śledzenia zmieni się z AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE w jednej klatce na AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING w następnej ramce, pozycja przeskakuje z miejsca początkowego, podaliśmy przybliżoną odległość do nowej lokalizacji z dokładną odległością. Ten natychmiastowa zmiana pozycji zmienia pozorną skalę obiektów, są zakotwiczone na obiekcie Ar InstantplacementPoint. To znaczy, że nagle obiekt jest większy lub mniejszy niż w poprzedniej ramce.

Wykonaj poniższe czynności, aby uniknąć wizualnego skoku spowodowanego nagłą zmianą widoczności. skala obiektu:

  1. Śledź pozycję i metodę śledzenia urządzenia ArInstantPlacementPoint w każdej klatce.
  2. Poczekaj, aż metoda śledzenia zmieni się na AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
  3. Użyj pozycji z poprzedniej i bieżącej, aby i określać odległość obiektu od urządzenia w obu klatkach.
  4. Oblicz zmianę widoczną na skali będącą wynikiem zmiany odległości od aparat fotograficzny.
  5. Dostosuj skalę obiektu, aby zareagować na zauważalną zmianę skali. aby obiekt nie zmienił się jego rozmiar.
  6. Opcjonalnie możesz płynnie dostosować skalę obiektu do jego pierwotnej wartości. na przestrzeni kilku klatek.
class WrappedInstantPlacement {
  ArInstantPlacementPoint* point;
  ArInstantPlacementPointTrackingMethod previous_tracking_method;
  float previous_distance_to_camera;
  float scale_factor = 1.0f;

 public:
  WrappedInstantPlacement(ArInstantPlacementPoint* point,
                          TrackingMethod previous_tracking_method,
                          float previous_distance_to_camera) {
    this.point = point;
    this.previous_tracking_method = previous_tracking_method;
    this.previous_distance_to_camera = previous_distance_to_camera;
  }
};

std::vector<WrappedInstantPlacement> wrapped_points_;

Po utworzeniu punktu dynamicznego miejsca docelowego zmodyfikuj OnTouched(), by dodać do niego punkt.

if (ar_trackable_type == AR_TRACKABLE_INSTANT_PLACEMENT_POINT) {
  ArInstantPlacementPoint* point = (ArInstantPlacementPoint*)ar_trackable;
  ArInstantPlacementPointTrackingMethod tracking_method;
  ArInstantPlacementPoint_getTrackingMethod(ar_session, point,
                                            &tracking_method);
  ArCamera* ar_camera = nullptr;
  ArFrame_acquireCamera(ar_session, ar_frame, &ar_camera);
  CHECK(ar_camera);
  wrapped_points_.push_back(WrappedInstantPlacement(
      point, tracking_method, Distance(point, ar_camera)));
}

Gdy metoda śledzenia punktu błyskawicznego miejsca docelowego przechodzi z AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE do: AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING, podaj odległość zapisany w celu przeciwdziałania widocznej zmianie skali.

void OnUpdate() {
  for (auto& wrapped_point : wrapped_points_) {
    ArInstantPlacementPoint* point = wrapped_point.point;

    ArTrackingState tracking_state = AR_TRACKING_STATE_STOPPED;
    ArTrackable_getTrackingState(ar_session, (ArTrackable)point,
                                 &tracking_state);

    if (tracking_state == AR_TRACKING_STATE_STOPPED) {
      wrapped_points_.remove(wrapped_point);
      continue;
    }
    if (tracking_state == AR_TRACKING_STATE_PAUSED) {
      continue;
    }

    ArInstantPlacementPointTrackingMethod tracking_method;
    ArInstantPlacementPoint_getTrackingMethod(ar_session, point,
                                              &tracking_method);
    ArCamera* ar_camera = nullptr;
    ArFrame_acquireCamera(ar_session, ar_frame, &ar_camera);
    CHECK(ar_camera);
    const float distance_to_camera = Distance(point, ar_camera);
    if (tracking_method ==
        AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE) {
      // Continue to use the estimated depth and pose. Record the distance to
      // the camera for use in the next frame if the transition to full
      // tracking happens.
      wrapped_point.previous_distance_to_camera = distance_to_camera;
    } else if (
        tracking_method ==
            AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING &&
        wrapped_point.previous_tracking_method ==
            AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE) {
      // Change from the estimated pose to the accurate pose. Adjust the
      // object scale to counteract the apparent change due to pose jump.
      wrapped_point.scale_factor =
          distance_to_camera / wrapped_point.previous_distance_to_camera;
      // Apply the scale factor to the model.
      // ...
      previous_tracking_method =
          AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING;
    }
  }
}

Możliwe spowolnienie działania witryny

Gdy wyszukiwanie dynamiczne jest włączone, ARCore zużywa dodatkowe cykle procesora. Jeśli Wydajność jest problemem, rozważ wyłączenie błyskawicznego miejsca docelowego po tym, udało się umieścić obiekt i metodę śledzenia całego wyszukiwania dynamicznego Zmieniono punkty za miejsce docelowe na AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING

Jeśli wyszukiwanie dynamiczne jest wyłączone, użyj opcji ArFrame_hitTest zamiast ArFrame_hitTestInstantPlacement

ArConfig* ar_config = NULL;
ArConfig_create(ar_session, &ar_config);
// Disable Instant Placement.
ArConfig_setInstantPlacementMode(ar_session, ar_config,
                                 AR_INSTANT_PLACEMENT_MODE_DISABLED);
CHECK(ArSession_configure(ar_session, ar_config) == AR_SUCCESS);
ArConfig_destroy(ar_config);