如何从Vuforia GL矩阵计算相机位置? [英] How to calculate the camera position from Vuforia GL matrix?

查看:182
本文介绍了如何从Vuforia GL矩阵计算相机位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我计算在Vuforia中渲染的SCNScene的相机位置.但是,对象并没有固定在标记上,而是在移动时跳来跳去.无论设备如何左右移动,场景中的立方体只能按正交显示.

I calculate the camera position of a SCNScene that is rendered in Vuforia. However the object is not staying fixed on the marker but jumping around when moving. The cube in the scene appears only orthographically, no matter how the device is moved around the sides cannot be seen.

每帧计算相机位置:

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

凝视照相机时计算照相机投影矩阵:

The camera projection matrix is calculated when the camera is stared:

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

我在做什么错了?

现在,当相机启动时,投影矩阵的计算如下:

The projection matrix is now calculated like this, when the camera starts:

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

相机位置每帧更新一次:

The camera position is updated with every frame:

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

通过移动设备并观察摄像机位置(左图)和旋转(右图)的日志记录,似乎轴是:

By moving the device and observing the logging of the camera position (left graph) and rotation (right graph) it seems that the axes are:

旋转轴与位置轴不同.同样,围绕其余轴旋转(在下图中未显示标题)对对0.999左右浮动的cameraNode.rotation.x值没有任何影响.

The axes for rotation are different from position axes. Also a rotation around the remaining axis (untitled in the graph below) does not have any influence on the cameraNode.rotation.x value which floats around 0.999.

这是怎么了?

推荐答案

您正在体验经典-我在矩阵中做错了"的行为,这需要大量的反复试验来解决.我还认为您一直在Vuforia的网站上阅读内容,这几乎是无济于事的. :)

You're experiencing classic - "I did something wrong with the matrix" behaviour that takes lots of trial-and-error to resolve. I also think you've been reading stuff on Vuforia's website which is almost never helpful. :)

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

Re-arranging the matrices is probably where you're going wrong. The SCNMatrix is supposed to be directly compatible with OpenGL. I actually put everything into the simd::matrix4x4 and use the built in SCNMatrix4FromMat4 to convert them to SCNMatrix.

SceneKit使用矩阵表示坐标空间转换, 反过来又可以代表组合的位置,旋转或 三维空间中对象的方向和比例. SceneKit矩阵结构以行优先顺序排列,因此它们是 适合传递给接受的着色器程序或OpenGL API 矩阵参数.

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.

所以,总而言之...我相信您应该删除:

So, to sum up... I believe you should delete:

SCNMatrix4 inverted = SCNMatrix4Invert(extrinsic);

对于将GLMatrix复制到SCNMatrix而不进行尝试,应该是正确的.比较使用您的方法生成的投影矩阵的结果进行挖掘.它们应该相同.

As for the copying of the GLMatrix to an SCNMatrix, without trying it, should be correct. Compare the result of the projection matrix generated using your method to mine. They should be identical.

我正在得到这样的投影矩阵:

I'm getting the projection matrix like this:

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

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

I convert the matrix to a simd::matrix4x4 (I spend a lot of time in C++-land) which is just an Apple defined struct for which SceneKit has support.

#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的对象,它实际上包含标识符和姿势,但是该姿势与投影矩阵只是相同的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
        }
}

这篇关于如何从Vuforia GL矩阵计算相机位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆