Entwicklerleitfaden für Instant Placements für Android NDK

Instant Placement API verwenden in Ihren eigenen Apps.

Vorbereitung

Machen Sie sich mit den grundlegenden AR-Konzepten vertraut. und Konfigurieren einer ARCore-Sitzung beschrieben, bevor du fortfährst.

Neue Sitzung mit Instant-Placement konfigurieren

Aktivieren Sie in einer neuen ARCore-Sitzung den Modus „Instant-Platzierung“.

// 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);

Objekt platzieren

Führen Sie in einer neuen ARCore-Sitzung einen Treffertest der Instant-Platzierung mit ArFrame_hitTestInstantPlacement Erstellen Sie dann ein neues ArAnchor mit dem Position von ArInstantPlacementPoint aus dem Trefferergebnis ARTrackable.

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);
}

Unterstützung für Instant-Placement Tracking der Bildschirmfläche mit der ungefähren Entfernung Automatischer Wechsel zum vollständigen Tracking, sobald der Punkt für die Instant-Platzierung erreicht wird in der realen Welt verankert. Rufen Sie die aktuelle Position ab mit ArInstantPlacementPoint_getPose() Aktuelle Tracking-Methode abrufen mit ArInstantPlacementPoint_getTrackingMethod()

ARCore kann zwar Treffertests für die Instant-Platzierung auf Oberflächen jeglicher Art durchführen, Ausrichtung wird in den Trefferergebnissen immer eine Position mit +Y nach oben angezeigt, der Schwerkraft. Auf horizontalen Oberflächen liefern Treffertests genaue Ergebnisse viel schneller zu platzieren.

Punkt-Tracking-Methode für die Instant-Platzierung überwachen

Wenn ARCore eine genaue 3D-Pose für die ArInstantPlacementPoint hat, die von ArFrame_hitTestInstantPlacement, beginnt mit der Tracking-Methode AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING Andernfalls beginnt sie mit der Tracking-Methode AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE. und wechseln zu AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING sobald ARCore eine genaue 3D-Pose hat. Sobald die Tracking-Methode AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING, wird nicht wiederhergestellt bis AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE.

Den Übergang zur Tracking-Methode gleichmäßiger gestalten

Wenn die Tracking-Methode von AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE in einem Frame zu AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING im nächsten Frame, wechselt die Pose von ihrer ursprünglichen Position hat die ungefähre Entfernung zu einem neuen Standort mit einer genauen Entfernung angegeben. Dieses Durch eine sofortige Änderung der Haltung ändert sich die Größe aller Objekte, sind am ArInstantPlacementPoint verankert. Das heißt, ein Objekt wird plötzlich größer oder kleiner als im vorherigen Frame erscheint.

Befolgen Sie diese Schritte, um den visuellen Sprung aufgrund der plötzlichen Änderung der Objektskalierung:

  1. Position und Tracking-Methode des ArInstantPlacementPoint im Blick behalten in jedem Frame.
  2. Warten Sie, bis sich die Verfolgungsmethode zu AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
  3. Mit der Pose aus dem vorherigen Frame und der Pose aus dem aktuellen Frame den Abstand des Objekts zum Gerät in beiden Frames ermitteln.
  4. Berechnen Sie die scheinbare Skalierungsänderung aufgrund der Abstandsänderung vom Kamera.
  5. Passen Sie die Größe des Objekts an, um der wahrgenommenen Größenänderung entgegenzuwirken. damit sich die Größe des Objekts nicht mehr ändert.
  6. Optional: Größe des Objekts reibungslos wieder auf die ursprüngliche Größe zurücksetzen über mehrere Frames hinweg.
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_;

Nachdem Sie den Punkt für die Instant-Platzierung erstellt haben, bearbeiten Sie OnTouched(), um ihn zu umschließen.

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)));
}

Wenn die Tracking-Methode des Punkts der Instant-Platzierung von AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE bis AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING, verwenden Sie die Entfernung um der scheinbaren Größenänderung entgegenzuwirken.

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;
    }
  }
}

Hinweise zur Leistung

Wenn die Instant-Platzierung aktiviert ist, verbraucht ARCore zusätzliche CPU-Zyklen. Wenn ist die Leistung ein wichtiger Faktor. Deaktivieren Sie gegebenenfalls die Instant-Platzierung, das Objekt und die Tracking-Methode aller Instant- Die Placement-Punkte wurden geändert zu AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING

Ist das Instant-Placement deaktiviert, verwenden Sie ArFrame_hitTest statt 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);