In ARCore, what is the best way to place a triangle in my world near Pose that I can use to intersect rays?

I am working with ARCore in Android Studio using java and trying to implement ray intersection with an object. I started with the Google example we provided (like here: https://developers.google.com/ar/develop/java/getting-started ). When you touch the screen, the beam is projected, and when this beam touches the plane, a snap to the plane (with an anchor / pose) is created at the intersection point.

Then I would like to place a 3D triangle in the world attached to this Pose. I am currently creating my Triangle based on a Pose translation, for example:

In HelloArActivity, during 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); } } } 

Note. I know that the coordinates of the triangle must be updated every time the coordinates of the Pose are updated. I left this since it is not part of my problem.

Triangular class

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

After that, clicking on the screen again, I create a beam projected from the worked out (x, y) part of the screen using Ian M, its sample code provided in answer to this question: how to check the intersection of the beam with an object in ARCore

Creating Ray in 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; } 

The result of this is that no matter where I click on the screen, it is always considered a hit (no matter what distance I add between the points in the triangle constructor).

I suspect this is due to the way the Pose is in the world, and using the Pose translation coordinates as a control point for my triangle is not the way, so I'm looking for the right way to do this, but any comments on other parts of my method are welcome!

I also tested my method for intersecting rays and triangles, and I don't think this is a problem, but I will include it here for completeness:

 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); Ix += r * dir.x; Iy += r * dir.y; Iz += r * dir.z; return I; } 

Thanks in advance!

+5
source share

Source: https://habr.com/ru/post/1272359/


All Articles