首页 文章

如何从 Vuforia GL 矩阵计算摄像机位置?

提问于
浏览
2

我计算在 Vuforia 中渲染的SCNScene的相机位置。然而,物体不会固定在标记上,而是在移动时跳跃。场景中的立方体只能在正交方向上出现,无论设备如何移动都无法看到。

每帧都计算相机位置:

// Get model view matrix
Vuforia::Matrix44F modelViewMatrix = Vuforia::Tool::convertPose2GLMatrix(result->getPose());

// Convert to extrinsic matrix
SCNMatrix4 extrinsic = [self SCNMatrix4FromVuforiaMatrix44: modelViewMatrix];
SCNMatrix4 inverted = SCNMatrix4Invert(extrinsic);

// Set new position of SCNCamera
cameraNode.transform = inverted;

摄像机投影矩阵是在摄像机开始时计算出来的:

// Get device camera calibration    
const Vuforia::CameraCalibration& cameraCalibration = Vuforia::CameraDevice::getInstance().getCameraCalibration();
projectionGLMatrix = Vuforia::Tool::getProjectionGL(cameraCalibration, 2.0f, 5000.0f);

// Convert matrix
GLKMatrix4 glkMatrix;

for(int i=0; i<16; i++) {
    glkMatrix.m[i] = projectionGLMatrix.data[i];
}

// Convert matrix
SCNMatrix4 projectionTransform = SCNMatrix4FromGLKMatrix4(glkMatrix);
cameraNode.camera.projectionTransform = projectionTransform;

我在这做错了什么?

更新 1

现在,当相机启动时,投影矩阵就像这样计算:

const Vuforia::CameraCalibration& cameraCalibration = Vuforia::CameraDevice::getInstance().getCameraCalibration();
Vuforia::Matrix44F vuforiaMatrix = Vuforia::Tool::getProjectionGL(cameraCalibration, 2.0f, 5000.0f);
matrix_float4x4 simdMatrix = simdMatrixWithVuforiaMatrix44F(vuforiaMatrix);
cameraNode.camera.projectionTransform = SCNMatrix4FromMat4(simdMatrix);

每帧都会更新相机位置:

Vuforia::Matrix44F modelViewMatrix = Vuforia::Tool::convertPose2GLMatrix(result->getPose());
matrix_float4x4 simdMatrix = simdMatrixWithVuforiaMatrix44F(modelViewMatrix);
cameraNode.transform = SCNMatrix4FromMat4(simdMatrix);

NSLog(@"camera position: x%lf, y%lf, z%lf, rotation: x%lf, y%lf, z%lf", _cameraNode.position.x, _cameraNode.position.y, _cameraNode.position.z, _cameraNode.rotation.x, _cameraNode.rotation.y, _cameraNode.rotation.z);

通过移动设备并观察摄像机位置(左图)和旋转(右图)的记录,似乎轴是:
在此输入图像描述

旋转轴与位置轴不同。围绕剩余轴的旋转(在下图中无标题)对 0.999 周围的 cameraNode.rotation.x 值没有任何影响。

这有什么不对?

1 回答

  • 2

    你正在体验经典 - “我做了一些错误的矩阵”行为需要很多 trial-and-error 来解决。我也认为你一直在阅读 Vuforia 网站上的内容,这几乎从来没有用过。 :)

    Re-arranging 矩阵可能是你出错的地方。 SCNMatrix应该与 OpenGL 直接兼容。我实际上把所有内容放入simd::matrix4x4并使用内置的SCNMatrix4FromMat4将它们转换为SCNMatrix

    SceneKit 使用矩阵来表示坐标空间变换,而坐标空间变换又可以表示 three-dimensional 空间中对象的组合位置,旋转或方向和比例。 SceneKit 矩阵结构按 row-major 顺序排列,因此适用于传递到接受矩阵参数的着色器程序或 OpenGL API。

    所以,总结一下......我相信你应该删除:

    SCNMatrix4 inverted = SCNMatrix4Invert(extrinsic);
    

    至于将GLMatrix复制到SCNMatrix,而不尝试它,应该是正确的。比较使用您的方法生成的投影矩阵的结果。它们应该完全相同。

    投影矩阵

    我得到的投影矩阵如下:

    const Vuforia::Matrix44F projectionMatrix = Vuforia::Tool::getProjectionGL(cameraCalibration, nearPlane, farPlane);
    simdMatrixWithVuforiaMatrix44F(projectionMatrix);
    

    我将矩阵转换为simd::matrix4x4(我在 C -land 中花了很多时间),这只是一个 Apple 定义的结构,SceneKit 支持它。

    #include <simd/simd.h>
    
    matrix_float4x4 simdMatrixWithVuforiaMatrix44F(const Vuforia::Matrix44F &matrix)
    {
        vector_float4 col0 = { matrix.data[0], matrix.data[1], matrix.data[2], matrix.data[3] };
        vector_float4 col1 = { matrix.data[4], matrix.data[5], matrix.data[6], matrix.data[7] };
        vector_float4 col2 = { matrix.data[8], matrix.data[9], matrix.data[10], matrix.data[11] };
        vector_float4 col3 = { matrix.data[12], matrix.data[13], matrix.data[14], matrix.data[15] };
    
        return matrix_from_columns(col0, col1, col2, col3);
    }
    

    回到视图控制器

    let extrinsic = SCNMatrix4FromMat4(projectionMatrix)
    _cameraNode?.camera?.projectionTransform = extrinsic
    

    Framemarker 构成

    我有一个名为 Framemarker 的对象实际上包含标识符和姿势,但该姿势与投影矩阵的simd::matrix4x4相同。

    for framemarker in framemarkers {
            switch framemarker.identifier {
            case 337:
                let pose = SCNMatrix4FromMat4(framemarker.pose)
                _firstNode?.transform = pose
                break
            case 357:
                let pose = SCNMatrix4FromMat4(framemarker.pose)
                _secondNode?.transform = pose
                break
            default:
                break
            }
    }
    

相关问题