swift - 如何从Vuforia GL矩阵计算相机位置?

标签 swift camera augmented-reality scenekit vuforia

我计算在 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);

通过移动设备并观察相机位置(左图)和旋转(右图)的记录,轴似乎是: enter image description here

旋转轴与位置轴不同。此外,围绕剩余轴(下图中无标题)的旋转不会对在 0.999 左右浮动的cameraNode.rotation.x 值产生任何影响。

这里出了什么问题?

最佳答案

您正在经历经典的“我在矩阵上做错了什么”行为,需要大量的反复试验才能解决。我还认为您一直在 Vuforia 网站上阅读内容,但这些内容几乎没有任何帮助。 :)

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

SceneKit uses matrices to represent coordinate space transformations, which in turn can represent the combined position, rotation or orientation, and scale of an object in three-dimensional space. SceneKit matrix structures are in row-major order, so they are suitable for passing to shader programs or OpenGL APIs that accept matrix parameters.

所以,总结一下......我认为你应该删除:

SCNMatrix4 inverted = SCNMatrix4Invert(extrinsic);

至于将GLMatrix复制到SCNMatrix,无需尝试,应该是正确的。将使用您的方法生成的投影矩阵的结果与我的方法进行比较。它们应该是相同的。

投影矩阵

我得到的投影矩阵是这样的:

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

我将矩阵转换为 simd::matrix4x4(我在 C++ 领域花费了大量时间),这只是 SceneKit 支持的 Apple 定义的结构。

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

返回 View Controller

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

帧标记姿势

我有一个名为 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
        }
}

关于swift - 如何从Vuforia GL矩阵计算相机位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42035046/

相关文章:

ios - 如何不断地将数据从父 ViewController 发送到 Container View Controller

ios - 将扩展添加到外部依赖项时中止陷阱 6

swift - NSCollectionView 的内容偏移量

android - 立即拍摄2张照片-使应用程序崩溃

ios - ARKit 在 ARWorldTrackingConfiguration 和 ARFaceTrackingConfiguration 之间切换 - 后置和前置摄像头

ios - 你知道如何使用 ARKIT 旋转 3D 模型以面对相机吗?

ios - 在 UITableView 中获取输入 onclick

javascript - 为 html 输入类型 : file 添加按钮到(浏览器)弹出菜单

android - 如何在 Android Emulator Camera 中模拟图片?

android - 增强现实 3D 模型渲染