Saiba como usar a API Instant Placement nos seus próprios apps.
Pré-requisitos
Entenda os conceitos fundamentais de RA. e como configurar uma sessão do ARCore antes de continuar.
Configurar uma nova sessão com a posição instantânea
Em uma nova sessão do ARCore, ative o modo de posicionamento instantâneo.
// 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);
Colocar um objeto
Em uma nova sessão do ARCore, faça um teste de hit de posicionamento instantâneo com
ArFrame_hitTestInstantPlacement
Em seguida, crie um novo ArAnchor
usando o
Posição de ArInstantPlacementPoint
do resultado do hit em 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); }
A posição instantânea é compatível com
rastreamento do espaço da tela com distância aproximada,
automaticamente para o rastreamento completo quando o ponto de posicionamento instantâneo for
ancorados no mundo real. Recuperar a pose atual com
ArInstantPlacementPoint_getPose()
Obtenha o método de acompanhamento atual com
ArInstantPlacementPoint_getTrackingMethod()
Embora o ARCore possa realizar testes de hit de posicionamento instantâneo em superfícies de qualquer os resultados de hits sempre retornarão uma pose com +Y para cima, em relação direção da gravidade. Em superfícies horizontais, os testes de hit retornam dados precisos. posições com muito mais rapidez.
Monitorar o método de acompanhamento de pontos do Canal instantâneo
Se o ARCore tiver uma pose 3D precisa para o ArInstantPlacementPoint
retornado por
ArFrame_hitTestInstantPlacement
, tudo começa com o método de acompanhamento
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
. Caso contrário, ele começará com o método de acompanhamento AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
.
e fazer a transição para AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
quando o ARCore tiver uma pose 3D precisa. Depois que o método de acompanhamento
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
, esta ação não será revertida
para
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
.
Suavizar a transição do método de acompanhamento
Quando o método de acompanhamento muda de
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
em um frame para AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
no frame seguinte, a pose salta de seu local inicial com base no
forneceu uma distância aproximada até um novo local a uma distância precisa. Isso
mudança instantânea na posição muda a escala aparente dos objetos que
são ancorados ao ArInstantplacementPoint. Ou seja, um objeto repentinamente
aparece maior ou menor do que no frame anterior.
Siga estas etapas para evitar o salto visual devido à mudança repentina no comportamento escala de objeto:
- Monitore a pose e o método de monitoramento do
ArInstantPlacementPoint
em cada frame. - Aguarde o método de acompanhamento mudar para
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
: - Use a pose do frame anterior e a do atual para determinar a distância do objeto até o dispositivo nos dois frames.
- Calcule a variação aparente da escala devido à mudança na distância do câmera.
- Ajustar a escala do objeto para neutralizar a mudança percebida em escala, para que o objeto não pareça mudar visualmente de tamanho.
- Opcionalmente, ajuste suavemente a escala do objeto de volta ao seu original em vários 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_;
Depois de criar o ponto de posicionamento instantâneo, modifique OnTouched()
para uni-lo.
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 o método de acompanhamento do ponto da posição instantânea muda de
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_SCREENSPACE_WITH_APPROXIMATE_DISTANCE
até AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
, use a distância
salva para neutralizar a aparente alteração de escala.
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;
}
}
}
Considerações sobre desempenho
Quando o Instant Placement está ativado, o ARCore consome ciclos de CPU adicionais. Se
de desempenho for uma preocupação, considere desativar a posição instantânea depois que o usuário
colocou o objeto e o método de acompanhamento de todos os itens instantâneos
Os pontos de posicionamento mudaram para
AR_INSTANT_PLACEMENT_POINT_TRACKING_METHOD_FULL_TRACKING
:
Quando a posição instantânea estiver desativada, use
ArFrame_hitTest
em vez de
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);