با نحوه استفاده از Instant Placement API در برنامه های خود آشنا شوید.
پیش نیازها
قبل از ادامه، مطمئن شوید که مفاهیم اساسی AR و نحوه پیکربندی یک جلسه ARCore را درک کرده اید.
یک جلسه جدید را با Instant Placement پیکربندی کنید
در یک جلسه ARCore جدید، حالت Instant Placement را فعال کنید.
// 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 جدید، تست ضربهای Instant Placement را با 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); }
Instant Placement از ردیابی فضای صفحه با فاصله تقریبی پشتیبانی میکند، پس از اینکه نقطه قرار دادن فوری در دنیای واقعی لنگر انداخته شد، به طور خودکار به ردیابی کامل تغییر میکند. حالت فعلی را با ArInstantPlacementPoint_getPose()
بازیابی کنید. روش ردیابی فعلی را با ArInstantPlacementPoint_getTrackingMethod()
دریافت کنید.
اگرچه ARCore میتواند تستهای ضربهگیری Instant Placement را در برابر سطوح با هر جهتی انجام دهد، نتایج ضربه همیشه یک حالت با +Y به بالا، برخلاف جهت گرانش، برمیگرداند. در سطوح افقی، تست های ضربه ای موقعیت های دقیق را بسیار سریعتر برمی گرداند.
روش ردیابی نقطه قرار دادن فوری را نظارت کنید
اگر ARCore یک حالت سه بعدی دقیق برای ArInstantPlacementPoint
ارائه شده توسط ArFrame_hitTestInstantPlacement
داشته باشد، با روش ردیابی AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
شروع می شود. در غیر این صورت، با روش ردیابی AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
شروع می شود و به محض اینکه ARCDore یک Po33 دقیق داشته باشد به AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
منتقل می شود. هنگامی که روش ردیابی 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
در فریم بعدی تغییر میکند، برنامه بر اساس فاصله زمانی دقیق به موقعیت مکانی جدید، یک پرش دقیق از موقعیت مکانی جدید را ارائه میکند. این تغییر آنی در حالت، مقیاس ظاهری هر شیئی را که به ArInstantPlacementPoint متصل شده اند، تغییر می دهد. یعنی یک شی به طور ناگهانی بزرگتر یا کوچکتر از آنچه در فریم قبلی بود به نظر می رسد.
برای جلوگیری از پرش بصری به دلیل تغییر ناگهانی در مقیاس ظاهری شی، این مراحل را دنبال کنید:
- ژست و روش ردیابی
ArInstantPlacementPoint
را در هر فریم پیگیری کنید. - منتظر بمانید تا روش ردیابی به
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
تغییر کند. - برای تعیین فاصله جسم تا دستگاه در هر دو فریم از حالت قاب قبلی و ژست در فریم فعلی استفاده کنید.
- تغییر ظاهری مقیاس به دلیل تغییر فاصله از دوربین را محاسبه کنید.
- مقیاس شی را برای خنثی کردن تغییر درک شده در مقیاس تنظیم کنید، به طوری که به نظر نمی رسد اندازه جسم از نظر بصری تغییر کند.
- در صورت تمایل، به آرامی مقیاس شی را به مقدار اولیه خود در چندین فریم تنظیم کنید.
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_;
پس از ایجاد نقطه Instant Placement، OnTouched()
را برای wrap تغییر دهید.
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;
}
}
}
ملاحظات عملکرد
وقتی Instant Placement فعال است، ARCore چرخه های CPU اضافی را مصرف می کند. اگر عملکرد نگران کننده است، پس از اینکه کاربر با موفقیت شی خود را قرار داد و روش ردیابی همه نقاط Instant Placement به AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
تغییر کرد، Instant Placement را غیرفعال کنید.
وقتی Instant Placement غیرفعال است، از 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);