没有平面的 ARCore 对象跟踪
Posted
技术标签:
【中文标题】没有平面的 ARCore 对象跟踪【英文标题】:ARCore object tracking without a plane 【发布时间】:2018-03-15 23:43:39 【问题描述】:我对这个 ARCore 很陌生,一直在看 SDK 中提供的 HelloAR Java android Studio 项目。
一切正常并且非常酷,但是,即使没有检测到平面,我也想在触摸屏幕时放置/放下一个对象。让我解释得更好一点...
据我了解 ARCore,它会检测水平面,并且仅在这些水平面上我可以放置 3D 对象以进行运动跟踪。
即使没有检测到水平面,是否有任何方法(可能使用 PointCloud 信息)能够在场景中放置对象?有点像这些例子? https://experiments.withgoogle.com/ar/flight-paths https://experiments.withgoogle.com/ar/arcore-drawing
我知道他们正在使用 Unity 和 openFrameworks,但是这可以用 Java 完成吗?
另外,我看过 How to put an object in the air? 和 how to check ray intersection with object in ARCore
但我不认为我理解 Ancor 的概念(我设法将对象放在场景中,但它要么立即消失,要么只是一个不了解现实世界的常规 OpenGL 对象。
我想了解的是: - 如何以及是否可以创建自定义/用户定义的平面,即 ARCore 不会自动检测到的平面? - 如何创建一个未链接到任何平面或链接到某个 PointCloud 点的 Ancor(我认为该示例在 PlaneAttachment 类中完成)? - 如何绘制对象并将其放置在先前创建的 Ancor 上?
我觉得这个问题太多了,但是查看 API 文档对我一点帮助都没有
谢谢!
编辑:
这是我添加到 HelloArActivity.java 中的代码(除了 // ***** 之后和之前的行之外,一切都与原始文件相同......
@Override
public void onDrawFrame(GL10 gl)
...
MotionEvent tap = mQueuedSingleTaps.poll();
// I added this to use screenPointToWorldRay function in the second link I posted... I am probably using this wrong
float[] worldXY = new float[6];
...
if (tap != null && frame.getTrackingState() == TrackingState.TRACKING)
// ***** I added this to use screenPointToWorldRay function
worldXY = screenPointToWorldRay(tap.getX(), tap.getY(), frame);
...
...
// Visualize anchors created by touch.
float scaleFactor = 1.0f;
for (PlaneAttachment planeAttachment : mTouches)
...
// ***** This places the object momentarily in the scene (it disappears immediately)
frame.getPose().compose(Pose.makeTranslation(worldXY[3], worldXY[4], worldXY[5])).toMatrix(mAnchorMatrix, 0);
// ***** This places the object in the middle of the scene but since it is not attached to anything, there is no tracking, it is always in the middle of the screen (pretty much expected behaviour)
// frame.getPose().compose(Pose.makeTranslation(0, 0, -1.0f)).toMatrix(mAnchorMatrix, 0);
// *****I duplicated this code which gets executed ONLY when touching a detected plane/surface.
mVirtualObject.updateModelMatrix(mAnchorMatrix, scaleFactor);
mVirtualObjectShadow.updateModelMatrix(mAnchorMatrix, scaleFactor);
mVirtualObject.draw(viewmtx, projmtx, lightIntensity);
mVirtualObjectShadow.draw(viewmtx, projmtx, lightIntensity);
...
【问题讨论】:
在没有飞机的情况下,你怎么知道该放在哪里?它会相对于设备框架放置吗? 另外,如果你设法放置了一些东西,但它没有完全工作,请附上“有点工作”的代码,这样我们也许可以指出应该改变什么才能让它工作. 这实际上是我的第二个问题...根据您的说法,如果没有平面,则无法放置对象...但是,PointCloud 点是否可以用作 Ancors 并因此具有可追踪对象?也许我根本不明白 PointCloud 是什么…… @李翔...是的!当使用那条线时,对象保持在同一位置并且不会消失。你能想出一种方法将 (x, y, z) 链接到 PointCloud 点或其他 Ancor 吗? @AlejandroMartinez 您找到解决问题的方法了吗? 【参考方案1】:您首先必须通过Frame.hitTest 执行命中测试并遍历 HitResult 对象,直到您命中 Point 类型的 Trackable。然后,您可以通过 HitResult.getHitPose 检索该命中结果的姿势,或将锚点附加到该点并通过 ArAnchor.getPose 获取该点的姿势(最佳方法)。
但是,如果您想从使用ArPointCloud.getPoints 检索到的任意点自己执行此操作,则需要做更多的工作。在这种方法中,问题有效地归结为“我如何从一个点推导出姿势/坐标基础?”。
在平面上工作时,导出姿势相对容易,因为您可以使用平面法线作为模型的向上 (y) 向量,并且可以选择 x 和 y 向量来配置您希望模型“面对”的位置“关于那架飞机。 (其中每个向量都垂直于其他向量)
当试图从一个点推导出一个基础时,您必须选择相对于您拥有的原点的所有三个向量(x、y 和 z)。您可以使用ArCamera.getViewMatrix 将向量 (0,1,0) 通过相机视图矩阵(假设您希望模型的顶部面向屏幕的顶部)转换为向上向量。然后,您可以选择 x 和 z 向量作为任意两个相互垂直的向量,将模型定向到您想要的方向。
【讨论】:
以上是关于没有平面的 ARCore 对象跟踪的主要内容,如果未能解决你的问题,请参考以下文章
ARCore – 如何在没有任何特征点的情况下在墙壁等表面上放置/创建对象?