我正在研究ARCore Google提供库。因为我需要将现实世界中的位置标记放置在相机中,所以我使用了ARCore库的LocationMarker类和其他LocationScene类,还创建了ViewRenderable来创建自定义视图可渲染,并将其放置在特定的LatLong中,但是我遇到的问题是,标记在移动相机时会不断渲染,并且在横向模式下无法正常工作。
在将设备从纵向模式旋转到横向模式时,放置在现实世界中的标记会不断渲染,并且在特定位置处不稳定。
在下面,我发布我的代码。
private void loadMarkers(List<LatLngLocation> latLngList) {
// clear the completable future map while again load the markers
completableFutureMap.clear();
// dynamic markers creation as per the list of latlng
markersViewRenderables = new CompletableFuture[latLngList.size()];
// create completableFuturemap for markers rending in location scene and put in to the map for manage
for (int i = 0; i < latLngList.size(); i++) {
LatLngLocation latlongLocation = latLngList.get(i);
CompletableFuture<ViewRenderable> completableFuture = null;
completableFuture = ViewRenderable.builder().setView(this, R.layout.location_marker_custom_view).build();
completableFutureMap.put(latlongLocation.getId(), completableFuture);
markersViewRenderables[i] = completableFuture;
}
// load all the completable viewrenderables
CompletableFuture.allOf(
markersViewRenderables)
.handle(
(notUsed, throwable) -> {
if (throwable != null) {
DemoUtils.displayError(this, "Unable to load renderables", throwable);
return null;
}
hasFinishedLoading = true;
return null;
});
// update the markers while camera moves and refresh the markers
sceneform_ar_scene_view.getArSceneView()
.getScene()
.addOnUpdateListener(
frameTime -> {
if (!hasFinishedLoading) {
return;
}
hideSpinner();
// while first time creating the markers
if (locationScene == null && !isLoadedMarkers) {
Location deviceLocation = new Location("provider");
deviceLocation.setLatitude(Double.parseDouble(PrefHelper.getInstance().getString(PrefHelper.DEVICE_LATITUDE, "")));
deviceLocation.setLongitude(Double.parseDouble(PrefHelper.getInstance().getString(PrefHelper.DEVICE_LONGITUDE, "")));
locationScene = new LocationScene(this, this, sceneform_ar_scene_view.getArSceneView());
locationScene.deviceLocation.currentBestLocation = deviceLocation;
// create location markers of the inbuilt class
for (int i = 0; i < latLngList.size(); i++) {
LatLngLocation latLngLocation = latLngList.get(i);
CompletableFuture<ViewRenderable> completableFuture = completableFutureMap.get(latLngLocation.getId());
Location destLocation = new Location("provider");
destLocation.setLatitude(latLngLocation.getLatLng().latitude);
destLocation.setLongitude(latLngLocation.getLatLng().longitude);
LocationMarker locationMarker = new LocationMarker(latLngLocation.getLatLng().latitude, latLngLocation.getLatLng().longitude, new Node());
ViewRenderable viewRenderable = null;
try {
viewRenderable = completableFuture.get();
viewRenderable.setSizer(new DpToMetersViewSizer(getResources().getDimensionPixelOffset(R.dimen._200sdp)));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
locationMarker.node.setRenderable(viewRenderable);
TextView tvLocationDistance = viewRenderable.getView().findViewById(R.id.tvLocationDistance);
TextView tvLocationName = viewRenderable.getView().findViewById(R.id.tvLocationName);
double distance = deviceLocation.distanceTo(destLocation);
double distance_in_km = distance / 1000;
tvLocationName.setText(latLngLocation.getLocationName());
tvLocationDistance.setText(String.format(Locale.ENGLISH, "%.2f KM", distance_in_km));
locationScene.mLocationMarkers.add(locationMarker);
isLoadedMarkers = true;
}
}
// get the arframe of arcamera
Frame frame = sceneform_ar_scene_view.getArSceneView().getArFrame();
if (frame == null) {
return;
}
if (frame.getCamera().getTrackingState() != TrackingState.TRACKING) {
return;
}
if (locationScene != null) {
locationScene.processFrame(frame);
}
if (loadingMessageSnackbar != null) {
for (Plane plane : frame.getUpdatedTrackables(Plane.class)) {
if (plane.getTrackingState() == TrackingState.TRACKING) {
hideLoadingMessage();
}
}
}
});
ARLocationPermissionHelper.requestPermission(this);
}
并且在locationMarker结果正确之后,我还对LocationScene类进行了自定义更改
if (((LocationMarker) this.mLocationMarkers.get(i)).anchorNode != null && ((LocationMarker) this.mLocationMarkers.get(i)).anchorNode.getAnchor() != null) {
((LocationMarker) this.mLocationMarkers.get(i)).anchorNode.getAnchor().detach();
}
Anchor newAnchor = this.mSession.createAnchor(frame.getCamera().getDisplayOrientedPose().compose(Pose.makeTranslation(xRotated, y + (float) heightAdjustment, zRotated)));
((LocationMarker) this.mLocationMarkers.get(i)).anchorNode = new LocationNode(newAnchor, (LocationMarker) this.mLocationMarkers.get(i), this);
((LocationMarker) this.mLocationMarkers.get(i)).anchorNode.setParent(this.mArSceneView.getScene());
((LocationMarker) this.mLocationMarkers.get(i)).anchorNode.addChild(((LocationMarker) this.mLocationMarkers.get(i)).node);
if (((LocationMarker) this.mLocationMarkers.get(i)).getRenderEvent() != null) {
((LocationMarker) this.mLocationMarkers.get(i)).anchorNode.setRenderEvent(((LocationMarker) this.mLocationMarkers.get(i)).getRenderEvent());
}
((LocationMarker) this.mLocationMarkers.get(i)).anchorNode.setScaleModifier(((LocationMarker) this.mLocationMarkers.get(i)).getScaleModifier());
((LocationMarker) this.mLocationMarkers.get(i)).anchorNode.setScaleAtDistance(((LocationMarker) this.mLocationMarkers.get(i)).shouldScaleAtDistance());
((LocationMarker) this.mLocationMarkers.get(i)).anchorNode.setHeight(((LocationMarker) this.mLocationMarkers.get(i)).getHeight());
我替换了锚点创建中的代码,该行是旧代码
frame.getCamera().getPose()
换成新的
frame.getCamera().getDisplayOrientedPose()
。
通过使用我在发布的问题to create renderables中创建上述工作代码的链接以及演示示例here,我正在发布所需的链接。