دليل مطوِّري المواضع الفورية لنظام التشغيل Android NDK

تعرَّف على كيفية استخدام واجهة برمجة تطبيقات ميزة "الموضع الفوري". في تطبيقاتك الخاصة.

المتطلبات الأساسية

احرص على فهم مفاهيم الواقع المعزّز الأساسية. وكيفية ضبط جلسة ARCore قبل المتابعة.

تهيئة جلسة جديدة باستخدام موضع الإعلان الفوري

في جلسة ARCore جديدة، قم بتمكين وضع الموضع الفوري.

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

وضع عنصر

في جلسة ARCore جديدة، أجرِ اختبار نتيجة لموضع الإعلان الفوري باستخدام ArFrame_hitTestInstantPlacement بعد ذلك، يمكنك إنشاء ArAnchor جديد باستخدام وضع ArInstantPlacementPoint من نتيجة 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);
}

دعم الموضع الفوري تتبُّع مساحة الشاشة مع المسافة التقريبية، التبديل التلقائي إلى التتبع الكامل بمجرد تحديد نقطة "الموضع الفوري" ثابتة في العالم الحقيقي. استعِد الوضع الحالي باستخدام ArInstantPlacementPoint_getPose() احصل على طريقة التتبع الحالية مع ArInstantPlacementPoint_getTrackingMethod()

على الرغم من أن ARCore يمكنه إجراء اختبارات نتيجة الموضع الفوري على أسطح أي من الأسطح الاتجاه، ستُظهر نتائج النتائج دائمًا الوضع مع +Y لأعلى، مقابل اتجاه الجاذبية. على الأسطح الأفقية، تعرض اختبارات النتائج نتائج دقيقة المواضع بشكل أسرع بكثير.

مراقبة طريقة تتبُّع نقاط الموضع الفوري

في حال كان لدى ARCore وضع ثلاثي الأبعاد دقيق لـ ArInstantPlacementPoint الذي تم عرضه من خلال ArFrame_hitTestInstantPlacement، تبدأ بطريقة التتبع AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING بخلاف ذلك، ستبدأ بطريقة التتبع AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE. والانتقال إلى AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING عندما يحصل ARCore على وضعية ثلاثية الأبعاد دقيقة. بمجرد تحديد طريقة AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING، لن يتم إرجاعها إلى AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE

تسهيل انتقال طريقة التتبع

عندما تتغير طريقة التتبع من AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE في إطار واحد من أجل AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING في الإطار التالي، يقفز الوضع من موقعه الأولي بناءً على توفير مسافة تقريبية إلى موقع جغرافي جديد على مسافة دقيقة. هذا النمط يؤدي التغير اللحظي في الوضعية إلى تغيير المقياس الواضح لأي كائنات ترتبط بـ ArInstantPositionPoint. أي كائن فجأة تظهر أكبر أو أصغر مما كانت عليه في الإطار السابق.

اتّبِع هذه الخطوات لتجنُّب الانتقال البصري بسبب التغيير المفاجئ في الواضح. مقياس الكائن:

  1. يمكنك تتبُّع وضعية "ArInstantPlacementPoint" وطريقة تتبُّعها. في كل إطار.
  2. انتظر حتى يتم تغيير طريقة التتبع إلى AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
  3. استخدم الوضعية من الإطار السابق والوضع في الإطار الحالي من أجل لتحديد مسافة الجسم في كلا الإطارين.
  4. احسب التغيير الواضح في المقياس بسبب التغيّر في المسافة من والكاميرا.
  5. اضبط مقياس الكائن لعكس التغيير الملحوظ في المقياس، بحيث لا يبدو أن الكائن يتغيّر بصريًا.
  6. اختياريًا، يمكنك ضبط مقياس الكائن بسلاسة إلى قيمته الأصلية. قيمة على عدة إطارات.
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_;

بعد إنشاء نقطة "موضع الإعلان الفوري"، عدِّل "OnTouched()" ليتم التفافها.

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

عندما تنتقل طريقة التتبع لنقطة الموضع الفوري من AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE إلى AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING، استخدم المسافة لإحداث تغيير واضح في المقياس.

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

اعتبارات الأداء

عند تفعيل ميزة "الموضع الفوري"، تستهلك ARCore دورات إضافية لوحدة المعالجة المركزية (CPU). في حال حذف بشأن الأداء أحد مصادر المخاوف، يمكنك تعطيل ميزة "الموضع الفوري" بعد أن ينقر المستخدم قد تم وضع الكائن الخاص بها بنجاح وطريقة التتبع لجميع عمليات البحث تغيرت نقاط الموضع إلى AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING

عند إيقاف موضع الإعلان الفوري، استخدم ArFrame_hitTest بدلاً من 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);