Scopri come utilizzare l'API Instant Placement nelle tue app.
Prerequisiti
Assicurati di aver compreso i concetti fondamentali di AR e di configurare una sessione ARCore prima di procedere.
Configurare una nuova sessione con il posizionamento istantaneo
In una nuova sessione ARCore, abilita la modalità Posizionamento istantaneo.
// 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);
Posizionare un oggetto
In una nuova sessione ARCore, esegui un hit test di posizionamento istantaneo con ArFrame_hitTestInstantPlacement
.
Quindi crea una nuova ArAnchor
usando la posa ArInstantPlacementPoint
del risultato dell'hit 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); }
Il Posizionamento istantaneo supporta il monitoraggio dello spazio sullo schermo con una distanza approssimativa, passando automaticamente al tracciamento completo una volta che il punto di Posizionamento istantaneo è ancorato nel mondo reale. Recupera la posizione attuale con
ArInstantPlacementPoint_getPose()
.
Ottieni il metodo di monitoraggio attuale con
ArInstantPlacementPoint_getTrackingMethod()
.
Anche se ARCore può eseguire hit test di posizionamento istantaneo su superfici con qualsiasi orientamento, i risultati degli hit restituiranno sempre una posa con +Y in alto, in contrasto con la direzione di gravità. Sulle superfici orizzontali, gli hit test restituiscono posizioni precise molto più velocemente.
Monitorare il metodo di monitoraggio dei punti del Posizionamento istantaneo
Se ARCore ha una posa 3D accurata per l'elemento ArInstantPlacementPoint
restituito da
ArFrame_hitTestInstantPlacement
, inizia con il metodo di monitoraggio
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
. In caso contrario, inizierà con il metodo di monitoraggio AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
e passerà a AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
una volta che ARCore avrà una posa 3D accurata. Una volta che il metodo di monitoraggio è AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
, non verrà ripristinato su AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
.
Semplifica la transizione del metodo di monitoraggio
Quando il metodo di monitoraggio passa da AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
in un frame a AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
nel frame successivo, la posa salta dalla posizione iniziale in base alla distanza approssimativa fornita a una nuova posizione a una distanza precisa. Questo
cambiamento istantaneo della posa cambia la scala apparente di tutti gli oggetti
ancorati ad Ar Instant PlacementPoint. Ciò significa che un oggetto appare improvvisamente
più grande o più piccolo rispetto al frame precedente.
Segui questi passaggi per evitare il salto visivo dovuto al cambiamento improvviso nella scala dell'oggetto apparente:
- Monitora la posa e il metodo di monitoraggio di
ArInstantPlacementPoint
in ogni frame. - Attendi che il metodo di monitoraggio passi a
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
. - Utilizza la posa del frame precedente e quella nell'attuale fotogramma per determinare la distanza dell'oggetto dal dispositivo in entrambi i fotogrammi.
- Calcola il cambiamento apparente di scala dovuto alla variazione di distanza dalla fotocamera.
- Regola la scala dell'oggetto per contrastare il cambiamento percepito di scala, in modo che l'oggetto non sembri cambiare visivamente di dimensione.
- Facoltativamente, ripristina il valore originale della scala dell'oggetto su più 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_;
Dopo aver creato il punto di Posizionamento istantaneo, modifica OnTouched()
per aggregarlo.
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)));
}
Quando il metodo di monitoraggio del punto di Posizionamento istantaneo passa da AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
a AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
, utilizza la distanza salvata per contrastare l'apparente variazione della scala.
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;
}
}
}
Considerazioni sul rendimento
Quando il posizionamento istantaneo è abilitato, ARCore consuma cicli della CPU aggiuntivi. Se
il rendimento è un problema, valuta la possibilità di disattivare il Posizionamento istantaneo dopo che l'utente
ha posizionato correttamente l'oggetto e il metodo di monitoraggio di tutti i punti
del Posizionamento istantaneo è cambiato in
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
.
Quando il posizionamento istantaneo è disattivato, utilizza
ArFrame_hitTest
anziché
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);