了解如何使用 Instant Placement API 。
前提条件
确保您了解 AR 基础概念 以及如何在继续之前配置 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
返回的 ArInstantPlacementPoint
提供了准确的 3D 位置方向,
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 有了准确的 3D 姿势。将跟踪方法
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()
以将其封装。
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 周期。如果
您担心广告效果,请考虑停用“即时展示位置”
成功放置了自己的对象和所有 免安装体验的跟踪方法
展示位置积分已更改为
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);