دليل مطوِّري المواضع الفورية لنظام التشغيل 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 في الإطار التالي، يقفز الوضع من موقعه الأولي بناء على المسافة التقريبية المقدمة إلى موقع جديد على مسافة دقيقة. ويغير هذا التغيير الفوري في الوضع المقياس الواضح لأي كائنات ارتساء موضع الإعلان الفوري موضع التطبيق. بمعنى أن الكائن يظهر فجأة أكبر أو أصغر مما كان في الإطار السابق.

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

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