Android NDK için Anında Yerleşim geliştirici kılavuzu

Anında Yerleşim API'sini kendi uygulamalarınızda nasıl kullanacağınızı öğrenin.

Ön koşullar

Devam etmeden önce temel AR kavramlarını ve ARCore oturumunu nasıl yapılandıracağınızı anladığınızdan emin olun.

Anında Yerleşim ile yeni bir oturum yapılandırma

Yeni bir ARCore oturumunda, Anında Yerleşim modunu etkinleştirin.

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

Nesne yerleştirme

Yeni bir ARCore oturumunda, ArFrame_hitTestInstantPlacement ile Anında Yerleşim isabet testi gerçekleştirin. Ardından, isabet sonucunun ARTrackable kısmındaki ArInstantPlacementPoint pozunu kullanarak yeni bir ArAnchor oluşturun.

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

Anında Yerleşim, yaklaşık mesafe ile ekran alanı izlemesini destekler ve Anında Yerleşim noktası gerçek dünyaya sabitlendiğinde otomatik olarak tam izlemeye geçiş yapar. Mevcut pozu ArInstantPlacementPoint_getPose() ile alın. ArInstantPlacementPoint_getTrackingMethod() ile geçerli izleme yöntemini edinin.

ARCore, herhangi bir yönde yer alan yüzeylerde Anında Yerleşim isabet testleri yapabilse de, isabet sonuçları yer çekimi yönünde her zaman +Y yukarı pozisyonu döndürür. Yatay yüzeylerde isabet testleri, doğru konumları çok daha hızlı döndürür.

Anında Yerleşim nokta izleme yöntemini izleme

ARCore, ArFrame_hitTestInstantPlacement tarafından döndürülen ArInstantPlacementPoint için doğru bir 3D pozisyona sahipse bu işlem AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING izleme yöntemiyle başlar. Aksi takdirde, AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE izleme yöntemiyle başlar ve ARCore doğru bir 3D pozuna sahip olduğunda AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING yöntemine geçer. İzleme yöntemi AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING olduğunda, AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE yöntemine geri döndürülmez.

İzleme yöntemi geçişini sorunsuz hale getirme

Takip yöntemi bir karede AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE değerinden sonraki karede AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING konumuna geçtiğinde, poz ilk konumundan doğru uzaktaki yeni bir konuma sağlanan yaklaşık uzaklığa göre atlar. Pozisyondaki bu anlık değişiklik, ArAnındaYerleşimPoint'e sabitlenmiş nesnelerin görünür ölçeğini değiştirir. Yani, bir nesne aniden önceki karede olduğundan daha büyük veya daha küçük görünür.

Görünen nesne ölçeğindeki ani değişiklikten dolayı görsel sıçrama yaşamamak için şu adımları uygulayın:

  1. Her karede ArInstantPlacementPoint pozisyonunu ve takip yöntemini takip edin.
  2. İzleme yönteminin AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING olarak değişmesini bekleyin.
  3. Her iki karede de nesnenin cihaza olan mesafesini belirlemek için önceki karedeki pozu ve geçerli karedeki pozu kullanın.
  4. Kameraya olan uzaklık değişikliğine bağlı olarak ölçekteki görünür değişikliği hesaplayın.
  5. Nesnenin ölçeğini, ölçekteki algılanan değişikliğe karşı koymak ve böylece görsel olarak boyut olarak değişmiyor gibi olacak şekilde ayarlayın.
  6. İsteğe bağlı olarak, birkaç karede nesnenin ölçeğini orijinal değerine düzgün bir şekilde ayarlayabilirsiniz.
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_;

Anında Yerleşim noktasını oluşturduktan sonra sarmalamak için OnTouched() değerini değiştirin.

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

Anında Yerleşim noktasının izleme yöntemi AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE'den AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING noktasına geçiş yaparken, görünür ölçek değişikliğini önlemek için kaydedilen mesafeyi kullanın.

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

Performansla ilgili konular

Anında Yerleşim etkinleştirildiğinde, ARCore ek CPU döngüleri kullanır. Performans sizin için sorun teşkil ediyorsa kullanıcı nesnesini başarıyla yerleştirdikten ve tüm Anında Yerleşim noktalarının izleme yöntemi AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING olarak değiştirildikten sonra Anında Yerleşim'i devre dışı bırakmayı düşünün.

Anında Yerleşim devre dışı bırakıldığında, ArFrame_hitTestInstantPlacement yerine ArFrame_hitTest kullanın.

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