VTK的ProjectionTransformMatrix和OpenGL的GL_PROJECTION有什么区别?

4
我在理解VTK中涉及的变换方面遇到了深刻的问题。OpenGL有相当好的文档,我认为VTK与OpenGL非常相似(在许多方面确实如此)。但是,当涉及到变换时,它似乎完全是另一回事。
这是一个关于OpenGL变换的好文档: http://www.songho.ca/opengl/gl_transform.html OpenGL中的透视投影矩阵是:

enter image description here

我希望看到这个在VTK中的公式是否能够给出VTK的投影矩阵(通过与VTK投影矩阵进行交叉检验)。
相关摄像机和渲染器参数:
camera->SetPosition(0,0,20);
camera->SetFocalPoint(0,0,0);
double crSet[2] = {10, 1000};
renderer->GetActiveCamera()->SetClippingRange(crSet);
double windowSize[2];
renderWindow->SetSize(1280,720);
renderWindowInteractor->GetSize(windowSize);
proj = renderer->GetActiveCamera()->GetProjectionTransformMatrix(windowSize[0]/windowSize[1], crSet[0], crSet[1]);

我得到的这个配置的投影变换矩阵是:

enter image description here

投影矩阵的 (3,3) 和 (3,4) 值(假设按行和列从 1 到 4 进行索引)应分别为 -(f+n)/(f-n) 和 -2*f*n/(f-n)。在我的 VTK 相机设置中,nearz 是 10,farz 是 1000,因此矩阵的 (3,3) 和 (3,4) 位置应分别为 -1.020 和 -20.20。但是实际结果却是 -1010 和 -10000。
我已更改裁剪范围值以查看更改情况,但 (3,3) 位置始终为 nearz+farz, 这对我来说毫无意义。此外,如果有人能解释为什么 (1,1) 和 (2,2) 位置的值为 3.7320,那就太好了。而且当我更改渲染器窗口的大小时,此值并不会改变。这对我来说相当令人困惑。
我在 VTKCamera 类参考文献中看到 GetProjectionTransformMatrix() 返回将相机坐标映射到视口坐标的转换矩阵。 VTK Camera Class Reference 以下是 OpenGL 渲染中涉及的变换的良好描述:

enter image description here

OpenGL投影矩阵是将眼坐标映射到剪裁坐标的矩阵。毫无疑问,OpenGL中的眼坐标与VTK中的相机坐标相同。但是,OpenGL中的剪裁坐标是否与VTK中的视口坐标相同?

我的目标是在VTK中模拟一个已经校准好的真实网络摄像头,以渲染3D模型。

1个回答

2
好的,你提供的文档已经解释了这个问题(我强调): vtkCamera::GetProjectionTransformMatrix:返回投影变换矩阵,将从相机坐标转换为视口坐标。此方法计算宽高比、近截面和远截面,然后调用更具体的签名GetCompositeProjectionTransformMatrix。 使用以下内容: vtkCamera::GetCompositeProjectionTransformMatrix:返回ViewTransform和ProjectionTransform的连接。此变换将世界坐标转换为视口坐标。 "aspect"是视口的宽度/高度,而nearz和farz是映射到近剪裁面和远剪裁面的Z缓冲区值。在视锥体内部的点的视口坐标位于([-1,+1],[-1,+1],[nearz,farz])范围内。 请注意,这既不符合OpenGL的窗口空间,也不符合规格化设备空间。如果发现该术语“视口坐标”对此来说不太恰当,但无论如何都是。更让我感到困扰的是,该矩阵实际上并没有转换到那个“视口空间”,而是转换到某个剪辑空间等效。只有进行透视分割后,坐标才会落在上述定义的“视口空间”的范围内。 但OpenGL的剪辑坐标和VTK的视口坐标相同吗? 所以答案很明确,否定的。但很接近。基本上,该投影矩阵只是将z维度缩放和移位,很容易在这两者之间进行转换。基本上,您只需从VTK的矩阵中取出znear和zfar,并将其放入您上面链接的OpenGL投影矩阵公式中,仅替换这两个矩阵元素即可。

谢谢你的建议。我的目标是使用真实的网络摄像头内部参数模拟VTK相机。摄像头的校准结果给出了焦距为646,uc=640和vc=360。使用这三个参数,我相信我可以修改投影矩阵。但在OpenGL中可能比较困难,因为文档的解释很明确。我不太明白你所说的从VTK矩阵中获取znear和zfar的意思。你能更详细地解释一下吗? - j1897
1
@technOslerphile:在VTK的矩阵M中,元素m22只是-(f+n),而m23-f*n。因此,您可以重建fn。但是您已经知道它们,所以可以直接使用它们。要将其转换为标准GL投影矩阵P,只需设置p22=m22/(f-n)p23=2*m23/(f-n)。请注意,这只是沿着z维度的比例和移位,基本上将VTK矩阵的[-f,-n]范围映射回GL期望的[-1,1]范围。 - derhass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接