使用 ARCore 检测平面和点击事件
Detecting planes and tap events with ARCore
我正在努力理解 Google's ARCore API and pushed their sample project (java_arcore_hello_ar
) to GitHub。
在此示例中,当您将应用程序部署到 Android 时,会检测到任何水平 surfaces/planes。如果您点击检测到的平面,"Andy" Andrid 机器人将呈现在您点击的位置。很帅
我正在尝试查找代码中的位置:
- 检测到水平 surface/plane;和
- 正确调整安迪大小和重新定向安迪的逻辑所在(我假设如果你点击的点离相机更远,他将被渲染得很小,等等)
我 相信 当检测到平面时,Android 框架会调用 onSurfaceCreated
方法:
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
// Create the texture and pass it to ARCore session to be filled during update().
mBackgroundRenderer.createOnGlThread(/*context=*/this);
mSession.setCameraTextureName(mBackgroundRenderer.getTextureId());
// Prepare the other rendering objects.
try {
mVirtualObject.createOnGlThread(/*context=*/this, "andy.obj", "andy.png");
mVirtualObject.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
mVirtualObjectShadow.createOnGlThread(/*context=*/this,
"andy_shadow.obj", "andy_shadow.png");
mVirtualObjectShadow.setBlendMode(BlendMode.Shadow);
mVirtualObjectShadow.setMaterialProperties(1.0f, 0.0f, 0.0f, 1.0f);
} catch (IOException e) {
Log.e(TAG, "Failed to read obj file");
}
try {
mPlaneRenderer.createOnGlThread(/*context=*/this, "trigrid.png");
} catch (IOException e) {
Log.e(TAG, "Failed to read plane texture");
}
mPointCloud.createOnGlThread(/*context=*/this);
}
但是该代码 看起来像 它假设用户已经点击了表面。我没有看到基本上说“Render Andy if 用户点击了检测到的 plane/surface。”。任何人都可以发现可能发生这种情况的地方吗?
敲击检测由 mGestureDetector:
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
onSingleTap(e);
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
});
链接到 SurfaceView
mSurfaceView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
这两件事都发生在 onCreate()
,所以现在每次点击表面视图(activity 中的 "main" 视图),
private void onSingleTap(MotionEvent e) {
// Queue tap if there is space. Tap is lost if queue is full.
mQueuedSingleTaps.offer(e);
}
被调用并存储了点击。然后在每一帧绘图中处理这个队列(这又是由系统的UI绘图周期发出的)here
MotionEvent tap = mQueuedSingleTaps.poll();
if (tap != null && frame.getTrackingState() == TrackingState.TRACKING) {
for (HitResult hit : frame.hitTest(tap)) {
...
这会添加一个新的锚点(即物理世界中的一个点 "locked"),在该锚点处呈现 Android 对象 (cf. this line)。
我正在努力理解 Google's ARCore API and pushed their sample project (java_arcore_hello_ar
) to GitHub。
在此示例中,当您将应用程序部署到 Android 时,会检测到任何水平 surfaces/planes。如果您点击检测到的平面,"Andy" Andrid 机器人将呈现在您点击的位置。很帅
我正在尝试查找代码中的位置:
- 检测到水平 surface/plane;和
- 正确调整安迪大小和重新定向安迪的逻辑所在(我假设如果你点击的点离相机更远,他将被渲染得很小,等等)
我 相信 当检测到平面时,Android 框架会调用 onSurfaceCreated
方法:
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
// Create the texture and pass it to ARCore session to be filled during update().
mBackgroundRenderer.createOnGlThread(/*context=*/this);
mSession.setCameraTextureName(mBackgroundRenderer.getTextureId());
// Prepare the other rendering objects.
try {
mVirtualObject.createOnGlThread(/*context=*/this, "andy.obj", "andy.png");
mVirtualObject.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
mVirtualObjectShadow.createOnGlThread(/*context=*/this,
"andy_shadow.obj", "andy_shadow.png");
mVirtualObjectShadow.setBlendMode(BlendMode.Shadow);
mVirtualObjectShadow.setMaterialProperties(1.0f, 0.0f, 0.0f, 1.0f);
} catch (IOException e) {
Log.e(TAG, "Failed to read obj file");
}
try {
mPlaneRenderer.createOnGlThread(/*context=*/this, "trigrid.png");
} catch (IOException e) {
Log.e(TAG, "Failed to read plane texture");
}
mPointCloud.createOnGlThread(/*context=*/this);
}
但是该代码 看起来像 它假设用户已经点击了表面。我没有看到基本上说“Render Andy if 用户点击了检测到的 plane/surface。”。任何人都可以发现可能发生这种情况的地方吗?
敲击检测由 mGestureDetector:
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
onSingleTap(e);
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
});
链接到 SurfaceView
mSurfaceView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
这两件事都发生在 onCreate()
,所以现在每次点击表面视图(activity 中的 "main" 视图),
private void onSingleTap(MotionEvent e) {
// Queue tap if there is space. Tap is lost if queue is full.
mQueuedSingleTaps.offer(e);
}
被调用并存储了点击。然后在每一帧绘图中处理这个队列(这又是由系统的UI绘图周期发出的)here
MotionEvent tap = mQueuedSingleTaps.poll();
if (tap != null && frame.getTrackingState() == TrackingState.TRACKING) {
for (HitResult hit : frame.hitTest(tap)) {
...
这会添加一个新的锚点(即物理世界中的一个点 "locked"),在该锚点处呈现 Android 对象 (cf. this line)。