Tìm hiểu cách sử dụng API Vị trí tức thì trong ứng dụng của riêng bạn.
Điều kiện tiên quyết
Hãy đảm bảo bạn hiểu rõ các khái niệm cơ bản về AR và cách định cấu hình một phiên ARCore trước khi tiếp tục.
Định cấu hình phiên mới bằng Vị trí tức thì
Trong phiên ARCore mới, hãy bật chế độ Vị trí tức thì.
// 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);
Đặt một đối tượng
Trong phiên ARCore mới, hãy thực hiện thử nghiệm lần truy cập Vị trí tức thì bằng
ArFrame_hitTestInstantPlacement
.
Sau đó, tạo một ArAnchor
mới bằng cách sử dụng tư thế ArInstantPlacementPoint
từ ARTrackable
của kết quả lượt truy cập.
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); }
Vị trí tức thì hỗ trợ
theo dõi không gian màn hình với khoảng cách gần đúng,
tự động chuyển sang theo dõi đầy đủ sau khi điểm Vị trí tức thì được
cố định trong thế giới thực. Truy xuất tư thế hiện tại bằng ArInstantPlacementPoint_getPose()
.
Nhận phương thức theo dõi hiện tại bằng ArInstantPlacementPoint_getTrackingMethod()
.
Mặc dù ARCore có thể thực hiện thử nghiệm lượt truy cập Vị trí tức thì trên các bề mặt thuộc bất kỳ hướng nào, nhưng kết quả lượt truy cập sẽ luôn trả về một tư thế có + Y hướng lên, ngược lại với hướng trọng lực. Trên các nền tảng ngang, phép kiểm thử lượt truy cập trả về vị trí chính xác nhanh hơn nhiều.
Theo dõi phương pháp theo dõi điểm Vị trí tức thì
Nếu ARCore có tư thế 3D chính xác cho ArInstantPlacementPoint
do ArFrame_hitTestInstantPlacement
trả về, thì ARCore sẽ bắt đầu bằng phương thức theo dõi AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
. Nếu không, quá trình này sẽ bắt đầu bằng phương thức theo dõi AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
và chuyển sang AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
sau khi ARCore có tư thế 3D chính xác. Khi là phương thức theo dõi là
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
, phương thức đó sẽ không hoàn nguyên về
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
.
Chuyển đổi phương pháp theo dõi dễ dàng
Khi phương pháp theo dõi thay đổi từ
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
trong một khung hình thành AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
trong khung hình tiếp theo, tư thế sẽ nhảy từ vị trí ban đầu dựa trên
khoảng cách gần đúng đã cung cấp đến một vị trí mới với khoảng cách chính xác. Sự thay đổi tức thì về tư thế này sẽ thay đổi tỷ lệ rõ ràng của mọi đối tượng được neo vào ArInstantPlacementPoint. Điều này nghĩa là một đối tượng đột nhiên xuất hiện lớn hơn hoặc nhỏ hơn so với đối tượng trong khung trước.
Hãy làm theo các bước sau để tránh hiện tượng nhảy vọt do sự thay đổi đột ngột về tỷ lệ rõ ràng của đối tượng:
- Theo dõi tư thế và phương pháp theo dõi của
ArInstantPlacementPoint
trong mỗi khung hình. - Chờ phương thức theo dõi thay đổi thành
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
. - Sử dụng tư thế từ khung trước và tư thế trong khung hiện tại để xác định khoảng cách của đối tượng đến thiết bị trong cả hai khung.
- Tính toán sự thay đổi rõ ràng về tỷ lệ do thay đổi về khoảng cách từ máy ảnh.
- Điều chỉnh tỷ lệ của đối tượng để chống lại sự thay đổi về tỷ lệ cảm nhận được để đối tượng không thay đổi về kích thước.
- Bạn có thể tuỳ ý điều chỉnh tỷ lệ của đối tượng về giá trị ban đầu trên một vài khung hình (không bắt buộc).
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_;
Sau khi tạo điểm Vị trí tức thì, hãy sửa đổi OnTouched()
để gói điểm này.
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)));
}
Khi phương pháp theo dõi của điểm Vị trí tức thì chuyển đổi từ
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
sang AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
, hãy sử dụng khoảng cách
đã lưu để chống lại sự thay đổi rõ ràng về tỷ lệ.
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;
}
}
}
Xem xét hiệu suất
Khi bật Vị trí tức thì, ARCore sẽ tiêu thụ thêm chu kỳ CPU. Nếu bạn lo ngại về hiệu suất, hãy cân nhắc tắt tính năng Vị trí tức thì sau khi người dùng đặt thành công đối tượng của họ và phương pháp theo dõi của tất cả các điểm Vị trí tức thì đã thay đổi thành AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
.
Khi tính năng Vị trí tức thì đang tắt, hãy sử dụng
ArFrame_hitTest
thay vì
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);