将 3D 世界 (arcore anchor/pose) 转换为其对应的 2D 屏幕坐标
Convert 3D world (arcore anchor/pose) to its corresponding 2D screen coordinates
我正在努力实现这种转变。在arcore中给定一个anchor Pose,如何获取其在屏幕中对应的二维坐标?
最后,经过几天的调查并从不同的资源中获取信息后,我终于能够完成这项工作。以下是从世界坐标(arcore 中的姿势)转换为 2D 屏幕坐标的代码片段(基于 arcore 示例 java 应用程序):
首先我们需要计算从世界变换的矩阵 --> 屏幕:
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);
arSceneView.getScene().getCamera().worldToScreenPoint();
按照描述为我工作 here。
我正在努力实现这种转变。在arcore中给定一个anchor Pose,如何获取其在屏幕中对应的二维坐标?
最后,经过几天的调查并从不同的资源中获取信息后,我终于能够完成这项工作。以下是从世界坐标(arcore 中的姿势)转换为 2D 屏幕坐标的代码片段(基于 arcore 示例 java 应用程序):
首先我们需要计算从世界变换的矩阵 --> 屏幕:
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);
arSceneView.getScene().getCamera().worldToScreenPoint();
按照描述为我工作 here。