在ARCore中,我如何最好地将一个三角形放置在Pose附近的世界中,我可以用它来进行光线交叉?

时间:2017-10-05 09:10:58

标签: java android arcore

我正在使用java在Android Studio中使用ARCore,并尝试与对象实现光线交叉。 我开始使用Google提供的示例(如下所示:https://developers.google.com/ar/develop/java/getting-started)。 在触摸屏幕时,投射光线,当此光线接触到平面时,会在交叉点创建PlaneAttachment(带有锚点/姿势)。

然后我想在这个Pose附带的世界中放置一个3D三角形。 目前我根据Pose的翻译创建了我的三角形,如下所示:

在HelloArActivity中,在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);
        }
    }
}

注意:我知道每次Pose的坐标更新时都应该更新三角形的坐标。我把它留下了,因为它不是我的问题的一部分。

三角课

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};
}

在此之后,再次点击屏幕时,我使用 Ian M 在此问题的答案中提供的代码示例创建从屏幕的抽头(x,y)部分投射的光线: how to check ray intersection with object in ARCore

Ray创建,在HelloArActivity中

/**
 * 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 (android 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;
}

然而,结果是,无论我在哪里点击屏幕,它总是算作一个命中(无论我在三角形的构造函数中添加了多少距离)。

怀疑这与Pose在世界上的位置有关,并且使用Pose的平移坐标作为我的三角形的参考点不是要走的路,所以我是寻找正确的方法来做到这一点,但欢迎任何关于我的方法的其他部分的评论!

此外,我已经测试了我的射线 - 三角形交叉方法,我不认为这是问题,但为了完整性,我会将其包含在这里:

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 个答案:

没有答案