Guida per gli sviluppatori del posizionamento istantaneo per Android NDK

Scopri come utilizzare l'API per il posizionamento istantaneo nelle tue app.

Prerequisiti

Assicurati di comprendere i concetti fondamentali della realtà aumentata e su come configurare una sessione ARCore prima di procedere.

Configura una nuova sessione con il posizionamento istantaneo

In una nuova sessione ARCore, attiva la modalità Posizionamento istantaneo.

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

Posiziona un oggetto

In una nuova sessione ARCore, esegui un hit test di posizionamento istantaneo con ArFrame_hitTestInstantPlacement Quindi crea una nuova ArAnchor utilizzando ArInstantPlacementPoint posa dal risultato dell'hit 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);
}

Il posizionamento istantaneo supporta monitoraggio dello spazio sullo schermo con distanza approssimativa, passaggio automatico al monitoraggio completo una volta che il punto di posizionamento istantaneo ancorate al mondo reale. Recupera la posa attuale con ArInstantPlacementPoint_getPose() Ottieni il metodo di monitoraggio corrente con ArInstantPlacementPoint_getTrackingMethod()

Sebbene ARCore possa eseguire hit test di posizionamento istantaneo su piattaforme di qualsiasi orientato, i risultati dei risultati restituiranno sempre una posa con +Y in alto, contro direzione della gravità. Sulle superfici orizzontali, gli hit test restituiscono dati accurati posizioni molto più velocemente.

Monitorare il metodo di monitoraggio dei punti di posizionamento istantaneo

Se ARCore ha una posa 3D precisa per ArInstantPlacementPoint restituito da ArFrame_hitTestInstantPlacement, inizia con il metodo di monitoraggio AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING In caso contrario, inizierà con il metodo di monitoraggio AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE. e la transizione a AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING una volta che ARCore ha una posa 3D precisa. Una volta che il metodo di monitoraggio AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING, l'operazione non verrà ripristinata a AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE.

Semplifica la transizione del metodo di monitoraggio

Quando il metodo di monitoraggio cambia da AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE in un frame a AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING nel frame successivo, la posa salta dalla sua posizione iniziale in base al fornita distanza approssimativa da un nuovo luogo a una distanza precisa. Questo un cambiamento istantaneo di posa cambia la scala apparente di qualsiasi oggetto sono ancorati ad ArInstancePLACEMENTPoint. In altre parole, un oggetto improvvisamente appare più grande o più piccolo rispetto al frame precedente.

Segui questi passaggi per evitare il salto visivo dovuto all'improvviso cambiamento di apparente scala dell'oggetto:

  1. Tieni traccia della posa e del metodo di rilevamento di ArInstantPlacementPoint in ogni frame.
  2. Attendi che il metodo di monitoraggio venga modificato in AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING.
  3. Usa la posa del frame precedente e quella nel frame corrente per determinare la distanza dell'oggetto dal dispositivo in entrambi i fotogrammi.
  4. Calcolare la variazione di scala apparente dovuta alla variazione della distanza dal fotocamera.
  5. Regolare la scala dell'oggetto per contrastare il cambiamento percepito di scala. in modo che le dimensioni dell'oggetto non sembrino cambiare visivamente.
  6. Se vuoi, puoi regolare facilmente la scala dell'oggetto per riportarlo alla sua originale su più frame.
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_;

Dopo aver creato il punto di posizionamento istantaneo, modifica OnTouched() per aggregarlo.

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

Quando il metodo di monitoraggio del punto di posizionamento istantaneo passa da AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE per AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING, utilizza la distanza salvate per contrastare la variazione apparente di scala.

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

Considerazioni sulle prestazioni

Quando il posizionamento istantaneo è attivato, ARCore consuma ulteriori cicli della CPU. Se è un problema, ti consigliamo di disattivare il posizionamento istantaneo dopo che ha posizionato correttamente l'oggetto e il metodo di monitoraggio di tutti i tipi di I punti di posizionamento sono cambiati in AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING.

Quando il posizionamento istantaneo è disattivato, utilizza ArFrame_hitTest anziché 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);