在ARCore的java中,如何在我的世界中最好地将一个三角形放置在一个可以用于光线相交的姿势附近?
我正在Android Studio中使用java与ARCore合作,并试图实现与对象的光线相交。 我从Google提供的示例开始(如这里所示:https://developers.google.com/ar/develop/java/getting-started)。 触摸屏幕时,将投影一条光线,当该光线接触平面时,将在交点中创建一个平面附件(带有锚定/姿势)
然后,我想把一个三维三角形的世界附加到这个姿势。 此时,我根据姿势的平移创建三角形,如下所示:
在活动中,在onDrawFrame(…)强>
//Code from sample, determining the hits on planes
MotionEvent tap = mQueuedSingleTaps.poll();
if (tap != null && frame.getTrackingState() == TrackingState.TRACKING) {
for (HitResult hit : frame.hitTest(tap)) {
// Check if any plane was hit, and if it was hit inside the plane polygon.
if (hit instanceof PlaneHitResult && ((PlaneHitResult) hit).isHitInPolygon()) {
mTouches.add(new PlaneAttachment(
((PlaneHitResult) hit).getPlane(),
mSession.addAnchor(hit.getHitPose())));
//creating a triangle in the world
Pose hitPose = hit.getHitPose();
float[] poseCoords = new float[3];
hitPose.getTranslation(poseCoords, 0);
mTriangle = new Triangle(poseCoords);
}
}
}
注意:我知道三角形的坐标应该在每次姿势坐标更新时更新。我忽略了这一点,因为这不是我的问题
三角形类
public class Triangle {
public float[] v0;
public float[] v1;
public float[] v2;
//create triangle around a given coordinate
public Triangle(float[] poseCoords){
float x = poseCoords[0], y = poseCoords[1], z = poseCoords[2];
this.v0 = new float[]{x+0.0001f, y-0.0001f, z};
this.v1 = new float[]{x, y+ 0.0001f, z-0.0001f};
this.v2 = new float[]{x-0.0001f, y, z+ 0.0001f};
}
在此之后,再次点击屏幕时,我使用回答此问题时提供的代码样本how to check ray intersection with object in ARCore创建一条从屏幕点击(x,y)部分投射的光线
光线创建,在活动中
/**
* Returns a world coordinate frame ray for a screen point. The ray is
* defined using a 6-element float array containing the head location
* followed by a normalized direction vector.
*/
float[] screenPointToWorldRay(float xPx, float yPx, Frame frame) {
float[] points = new float[12]; // {clip query, camera query, camera origin}
// Set up the clip-space coordinates of our query point
// +x is right:
points[0] = 2.0f * xPx / mSurfaceView.getMeasuredWidth() - 1.0f;
// +y is up (安卓 UI Y is down):
points[1] = 1.0f - 2.0f * yPx / mSurfaceView.getMeasuredHeight();
points[2] = 1.0f; // +z is forwards (remember clip, not camera)
points[3] = 1.0f; // w (homogenous coordinates)
float[] matrices = new float[32]; // {proj, inverse proj}
// If you'll be calling this several times per frame factor out
// the next two lines to run when Frame.isDisplayRotationChanged().
mSession.getProjectionMatrix(matrices, 0, 1.0f, 100.0f);
Matrix.invertM(matrices, 16, matrices, 0);
// Transform clip-space point to camera-space.
Matrix.multiplyMV(points, 4, matrices, 16, points, 0);
// points[4,5,6] is now a camera-space vector. Transform to world space to get a point
// along the ray.
float[] out = new float[6];
frame.getPose().transformPoint(points, 4, out, 3);
// use points[8,9,10] as a zero vector to get the ray head position in world space.
frame.getPose().transformPoint(points, 8, out, 0);
// normalize the direction vector:
float dx = out[3] - out[0];
float dy = out[4] - out[1];
float dz = out[5] - out[2];
float scale = 1.0f / (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
out[3] = dx * scale;
out[4] = dy * scale;
out[5] = dz * scale;
return out;
}
然而,这样做的结果是,无论我在哪里点击屏幕,它总是算作点击(无论我在三角形的构造函数中在点之间添加了多少距离)
我怀疑这与姿势在世界上的位置有关,使用姿势的平移坐标作为三角形的参考点不是一个好办法,所以我正在寻找正确的方法,但欢迎对我的方法的其他部分发表任何评论
此外,我已经测试了我的光线三角形相交方法,我认为这不是问题所在,但为了完整性,我将在这里包括它:
public Point3f intersectRayTriangle(CustomRay R, Triangle T) {
Point3f I = new Point3f();
Vector3f u, v, n;
Vector3f dir, w0, w;
float r, a, b;
u = new Vector3f(T.V1);
u.sub(new Point3f(T.V0));
v = new Vector3f(T.V2);
v.sub(new Point3f(T.V0));
n = new Vector3f(); // cross product
n.cross(u, v);
if (n.length() == 0) {
return null;
}
dir = new Vector3f(R.direction);
w0 = new Vector3f(R.origin);
w0.sub(new Point3f(T.V0));
a = -(new Vector3f(n).dot(w0));
b = new Vector3f(n).dot(dir);
if ((float)Math.abs(b) < SMALL_NUM) {
return null;
}
r = a / b;
if (r < 0.0) {
return null;
}
I = new Point3f(R.origin);
I.x += r * dir.x;
I.y += r * dir.y;
I.z += r * dir.z;
return I;
}
提前谢谢
共 (0) 个答案