2017-02-04 58 views
2

我计算了在Vuforia中渲染的SCNScene的相机位置。然而,物体并没有固定在标记上,而是在移动时跳跃。场景中的立方体只出现在正确的位置,无论设备如何在两侧移动都看不到。如何从Vuforia GL矩阵计算相机位置?

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

旋转轴与位置轴不同。此外,围绕剩余轴的旋转(在下图中未命名)对cameraNode.rotation.x值没有任何影响,该值浮动在0.999左右。

这里有什么问题?

回答

2

您正在体验经典 - “我做了矩阵错误”的行为,需要大量的反复试验才能解决。我也认为你一直在阅读Vuforia网站上的内容,这几乎毫无帮助。 :)

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

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

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

SCNMatrix4 inverted = SCNMatrix4Invert(extrinsic); 

对于GLMatrix的复制到SCNMatrix,没有尝试它,应该是正确的。比较使用您的方法生成的投影矩阵的结果。它们应该是相同的。

投影矩阵

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

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

我的矩阵转换为simd::matrix4x4(我花了很多的C++时间 - 土地),这仅仅是一个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 
     } 
} 
+0

谢谢,相机的x,y,z位置与您的方法相同。但是,我有同样的问题,当我移动设备时,物体不会停留在派克上。将设备移动到右侧(+ x)​​不会将渲染对象移动到屏幕左侧。这里是一个视频,更好地解释它:https://dl.dropboxusercontent.com/u/71604584/vuforia_1.m4v – Manuel

+0

我刚刚意识到我只更新'renderFrameVuforia'中相机的投影矩阵,但不能转换任何其他节点的场景。这是原因吗?顺便说一句。我正在使用SCNRenderer。 – Manuel

+1

投影矩阵在开始时更新一次,之后您需要在每个刷新/回调中更新表示对象的节点的姿态。 –