Pelajari cara menggunakan Instant Placement API di aplikasi Anda sendiri.
Prasyarat
Pastikan Anda memahami konsep AR dasar dan cara mengonfigurasi sesi ARCore sebelum melanjutkan.
Mengonfigurasi sesi baru dengan Penempatan Instan
Di sesi ARCore baru, aktifkan mode Penempatan Instan.
// 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);
Menempatkan objek
Dalam sesi ARCore baru, lakukan hit-test Penempatan Instan dengan ArFrame_hitTestInstantPlacement
.
Kemudian, buat ArAnchor
baru menggunakan
pose ArInstantPlacementPoint
dari ARTrackable
hasil hit.
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); }
Penempatan Instan mendukung pelacakan ruang layar dengan perkiraan jarak, yang secara otomatis beralih ke pelacakan penuh setelah titik Penempatan Instan ditautkan di dunia nyata. Mengambil pose saat ini dengan
ArInstantPlacementPoint_getPose()
.
Mendapatkan metode pelacakan saat ini dengan
ArInstantPlacementPoint_getTrackingMethod()
.
Meskipun ARCore dapat melakukan hit-test Penempatan Instan terhadap permukaan orientasi apa pun, hasil hit akan selalu menampilkan pose dengan +Y ke atas, terhadap arah gravitasi. Pada permukaan horizontal, hit-test menampilkan posisi yang akurat dengan jauh lebih cepat.
Memantau metode pelacakan titik Penempatan Instan
Jika ARCore memiliki pose 3D yang akurat untuk ArInstantPlacementPoint
yang ditampilkan oleh
ArFrame_hitTestInstantPlacement
, ARCore akan dimulai dengan metode pelacakan
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
. Jika tidak, ARCore akan dimulai dengan metode pelacakan AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
dan beralih ke AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
setelah ARCore memiliki pose 3D yang akurat. Setelah metode pelacakan
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
, metode tersebut tidak akan dikembalikan
ke
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
.
memperlancar transisi metode pelacakan
Saat metode pelacakan berubah dari
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
dalam satu frame ke AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
di frame berikutnya, pose akan melompat dari lokasi awalnya berdasarkan
perkiraan jarak yang diberikan ke lokasi baru pada jarak yang akurat. Perubahan
pose instan ini mengubah skala yang jelas dari setiap objek yang
ditambatkan ke ArInstantPlacementPoint. Artinya, sebuah objek tiba-tiba
tampak lebih besar atau lebih kecil daripada di {i>frame<i} sebelumnya.
Ikuti langkah-langkah berikut untuk menghindari lompatan visual karena perubahan mendadak pada skala objek yang terlihat:
- Lacak pose dan metode pelacakan
ArInstantPlacementPoint
di setiap frame. - Tunggu hingga metode pelacakan berubah menjadi
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
. - Gunakan pose dari frame sebelumnya dan pose dalam frame saat ini untuk menentukan jarak objek ke perangkat di kedua frame.
- Hitung perubahan skala yang terlihat karena perubahan jarak dari kamera.
- Sesuaikan skala objek untuk melawan perubahan skala yang dirasakan, sehingga objek tidak tampak berubah ukurannya secara visual.
- Secara opsional, sesuaikan skala objek kembali ke nilai aslinya dengan lancar melalui beberapa frame.
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_;
Setelah membuat titik Penempatan Instan, ubah OnTouched()
untuk menggabungkannya.
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)));
}
Saat metode pelacakan titik Penempatan Instan bertransisi dari
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
ke AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
, gunakan jarak
yang disimpan untuk menangkal perubahan skala yang jelas.
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;
}
}
}
Pertimbangan performa
Jika Penempatan Instan diaktifkan, ARCore akan menggunakan siklus CPU tambahan. Jika
performa menjadi masalah, pertimbangkan untuk menonaktifkan Penempatan Instan setelah pengguna
berhasil menempatkan objek dan metode pelacakan semua titik
Penempatan Instan telah berubah menjadi
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
.
Jika Penempatan Instan dinonaktifkan, gunakan
ArFrame_hitTest
, bukan
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);