Guide du développeur sur l'emplacement instantané pour le NDK Android

Découvrez comment utiliser l'API Instant Placement. dans vos propres applications.

Prérequis

Assurez-vous de bien maîtriser les concepts fondamentaux de la RA. et comment configurer une session ARCore avant de continuer.

Configurer une nouvelle session à l'aide des emplacements instantanés

Dans une nouvelle session ARCore, activez le mode Emplacement instantané.

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

Placer un objet

Dans une nouvelle session ARCore, effectuez un test de positionnement instantané des emplacements avec ArFrame_hitTestInstantPlacement Créez ensuite un autre ArAnchor à l'aide de la méthode ArInstantPlacementPoint pose à partir des ARTrackable du résultat de l'appel.

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

Emplacement instantané compatible suivi de l'espace à l'écran avec distance approximative passe automatiquement au suivi complet une fois que le point d'emplacement instantané est ancré dans le monde réel. Récupérez la pose actuelle avec ArInstantPlacementPoint_getPose() Obtenez la méthode de suivi actuelle avec ArInstantPlacementPoint_getTrackingMethod()

Bien qu'ARCore puisse effectuer des tests de positionnement instantanés des emplacements sur les surfaces l'orientation, les résultats de hit renvoient toujours une pose avec +Y vers le haut, par rapport à la dans la direction de la gravité. Sur les surfaces horizontales, les tests de positionnement renvoient bien plus vite.

Surveiller la méthode de suivi des points pour les emplacements instantanés

Si ARCore a une position 3D précise pour l'élément ArInstantPlacementPoint renvoyé par ArFrame_hitTestInstantPlacement, cela commence par la méthode de suivi AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING Sinon, il commencera par la méthode de suivi AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE. et passer à AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING une fois qu'ARCore a trouvé une bonne posture en 3D. Une fois que la méthode de suivi est La valeur AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING ne sera pas rétablie. à AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE

Faciliter la transition vers la méthode de suivi

Lorsque la méthode de suivi passe AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE dans une image sur AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING dans l'image suivante, la pose saute depuis son emplacement initial en fonction a fourni une distance approximative vers un nouveau lieu à une distance précise. Ce tout changement instantané de position modifie l'échelle apparente de tout objet sont ancrées à ArInstantPlacementPoint. C'est-à-dire qu'un objet soit plus grande ou plus petite que dans l'image précédente.

Suivez ces étapes pour éviter le saut visuel dû au changement soudain de l'apparente échelle d'objet:

  1. Effectuez le suivi de la posture et de la méthode de suivi de l'ArInstantPlacementPoint. dans chaque image.
  2. Attendez que la méthode de suivi passe à AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
  3. Utilisez la posture du cadre précédent et celle du cadre actuel pour effectuer les actions suivantes : déterminer la distance entre l'objet et l'appareil dans les deux images.
  4. Calculer la variation apparente de l'échelle due à la variation de la distance par rapport caméra.
  5. Ajustez l’échelle de l’objet pour contrebalancer le changement d’échelle perçu afin que la taille de l'objet ne semble pas changer visuellement.
  6. Vous pouvez aussi ajuster progressivement la taille de l'objet à sa taille d'origine. sur plusieurs frames.
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_;

Après avoir créé le point d'emplacement instantané, modifiez OnTouched() pour l'encapsuler.

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

Lorsque la méthode de suivi du point Emplacement instantané passe du AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE à AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING, utilisez la distance économisés pour contrebalancer ce changement d'échelle.

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

Considérations sur les performances

Lorsque l'emplacement instantané est activé, ARCore consomme des cycles de processeur supplémentaires. Si les performances sont préoccupantes, envisagez de désactiver l'emplacement instantané une fois que l'utilisateur a placé correctement son objet et la méthode de suivi de toutes les recherches instantanées Les points d'emplacement ont été remplacés par AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING

Lorsque l'emplacement instantané est désactivé, utilisez ArFrame_hitTest au lieu de 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);