我正在努力实现这种转变。给定锚定姿势在arcore中,如何在屏幕中获取其相应的2D坐标?
最终,经过几天的调查并从不同的资源中获取了信息,我才能够使它工作。以下是一个代码片段(基于arcore示例Java应用),用于将World坐标(Arcore中的位姿)转换为2D屏幕坐标:
首先,我们需要计算要从世界->屏幕转换的矩阵:
public float[] calculateWorld2CameraMatrix(float[] modelmtx, float[] viewmtx, float[] prjmtx) { float scaleFactor = 1.0f; float[] scaleMatrix = new float[16]; float[] modelXscale = new float[16]; float[] viewXmodelXscale = new float[16]; float[] world2screenMatrix = new float[16]; Matrix.setIdentityM(scaleMatrix, 0); scaleMatrix[0] = scaleFactor; scaleMatrix[5] = scaleFactor; scaleMatrix[10] = scaleFactor; Matrix.multiplyMM(modelXscale, 0, modelmtx, 0, scaleMatrix, 0); Matrix.multiplyMM(viewXmodelXscale, 0, viewmtx, 0, modelXscale, 0); Matrix.multiplyMM(world2screenMatrix, 0, prjmtx, 0, viewXmodelXscale, 0); return world2screenMatrix;
}
一旦有了这个矩阵,就可以将点从3D世界投影到2D,但是在投影过程中,我们必须将NDC坐标转换为屏幕。以下是执行此转换的方法:
double[] world2Screen(int screenWidth, int screenHeight, float[] world2cameraMatrix) { float[] origin = {0f, 0f, 0f, 1f}; float[] ndcCoord = new float[4]; Matrix.multiplyMV(ndcCoord, 0, world2cameraMatrix, 0, origin, 0); ndcCoord[0] = ndcCoord[0]/ndcCoord[3]; ndcCoord[1] = ndcCoord[1]/ndcCoord[3]; double[] pos_2d = new double[]{0,0}; pos_2d[0] = screenWidth * ((ndcCoord[0] + 1.0)/2.0); pos_2d[1] = screenHeight * (( 1.0 - ndcCoord[1])/2.0); return pos_2d; }
最后,一个简单的用法示例:
DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); int height = displayMetrics.heightPixels; int width = displayMetrics.widthPixels; // Get projection matrix. float[] projmtx = new float[16]; camera.getProjectionMatrix(projmtx, 0, 0.1f, 100.0f); // Get camera matrix and draw. float[] viewmtx = new float[16]; camera.getViewMatrix(viewmtx, 0); float[] anchorMatrix = new float[16]; anchor.getPose().toMatrix(anchorMatrix, 0); float[] world2screenMatrix = virtualObject.calculateWorld2CameraMatrix(anchorMatrix, viewmtx, projmtx); double[] anchor_2d = world2Screen(width, height, world2screenMatrix);