Instant Placement developer guide for Android NDK

Learn how to use the Instant Placement API in your own apps.

Prerequisites

Make sure that you understand fundamental AR concepts and how to configure an ARCore session before proceeding.

Configure a new session with Instant Placement

In a new ARCore session, enable Instant Placement mode.

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

Place an object

In a new ARCore session, perform an Instant Placement hit-test with ArFrame_hitTestInstantPlacement . Then create a new ArAnchor using the ArInstantPlacementPoint pose from the hit result's 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 supports screen space tracking with approximate distance , automatically switching to full tracking once the Instant Placement point is anchored in the real world. Retrieve the current pose with ArInstantPlacementPoint_getPose() . Get the current tracking method with ArInstantPlacementPoint_getTrackingMethod() .

Although ARCore can perform Instant Placement hit-tests against surfaces of any orientation, hit results will always return a pose with +Y up, against the direction of gravity. On horizontal surfaces, hit-tests return accurate positions much faster.

Monitor the Instant Placement point tracking method

If ARCore has an accurate 3D pose for the ArInstantPlacementPoint returned by ArFrame_hitTestInstantPlacement , it starts with tracking method AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING . Otherwise, it will start with tracking method AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE and transition to AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING once ARCore has an accurate 3D pose. Once the tracking method is AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING , it will not revert to AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE .

Smooth the tracking method transition

When the tracking method changes from AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE in one frame to AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING in the next frame, the pose jumps from its initial location based on the provided approximate distance to a new location at an accurate distance. This instantaneous change in pose changes the apparent scale of any objects that are anchored to the ArInstantPlacementPoint. That is, an object suddenly appears larger or smaller than it was in the previous frame.

Follow these steps to avoid the visual jump due to the sudden change in apparent object scale:

  1. Keep track of the pose and tracking method of the ArInstantPlacementPoint in each frame.
  2. Wait for the tracking method to change to AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING .
  3. Use the pose from the previous frame and the pose in the current frame to determine the object's distance to the device in both frames.
  4. Calculate the apparent change in scale due to the change in distance from the camera.
  5. Adjust the scale of the object to counteract the perceived change in scale, so that the object does not appear to visually change in size.
  6. Optionally, smoothly adjust the scale of the object back to its original value over several frames.
  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_ 
 ; 
 

After creating the Instant Placement point, modify OnTouched() to wrap it.

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

When the tracking method of the Instant Placement point transitions from AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE to AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING , use the distance saved to counteract the apparent scale change.

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

Performance considerations

When Instant Placement is enabled, ARCore consumes additional CPU cycles. If performance is a concern, consider disabling Instant Placement after the user has successfully placed their object and the tracking method of all Instant Placement points have changed to AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING .

When Instant Placement is disabled, use ArFrame_hitTest instead of 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 
 ); 
Design a Mobile Site
View Site in Mobile | Classic
Share by: