旋转一个不对称的截头体
Rotating an asymmetric frustum
在我的程序中,我在投影矩阵中定义了一个不对称截头体,它会随着用户的位置而变化。如果一个平面的所有z值都在同一位置,我的程序工作得很好。但是,如果观察平面稍微旋转了一点(沿Y方向旋转),则我通过在ModelView
矩阵中执行glRotate
来旋转相机。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(topLeftX, bottomRightX, bottomRightY, topLeftY, camNear, camFar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(xHeadPosition, yHeadPosition, zHead, xHeadPosition, yHeadPosition, zHead -1 , 0, 1, 0);
glTranslatef(400, 0); //Rotating with the right side of the plane as the pivot
glRotatef(yRotation, 0, 1, 0);
glTranslatef(-400, 0);
然而,我想在投影中也这样做,以保持MV矩阵的干净。我试着做同样的事情如下:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(400, 0); // Pre-multiplication here as opposed to post-mulitplication in MV matrix
glRotatef(yRotation, 0, 1, 0);
glTranslatef(-400, 0);
glFrustum(topLeftX, bottomRightX, bottomRightY, topLeftY, camNear, camFar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(xHeadPosition, yHeadPosition, zHead, xHeadPosition, yHeadPosition, zHead -1 , 0, 1, 0);
然而,上面的内容并没有给我所需的输出,而且它似乎并没有旋转投影平面,使观看平面对用户/相机来说是前置的。如何旋转投影平面,使其对用户来说变成腱前的?
我认为您确实需要了解glLoadIdentity的功能。它丢弃矩阵堆栈顶部的任何内容,并将其替换为恒等式。在这些glLoadIdentity调用之间,glTranslate和glRotate没有任何影响(除了消耗一些CPU时间和内存带宽)。类似于gluLookAt之前的glLoadIdentity渲染nil,就像glFrustum所做的那样。
我的建议是:读一本关于线性代数的书,尤其是矩阵数学,然后读一本有关3D图形数学的书,了解如何将之前从书中学到的抽象概念发挥作用。
然后您应该熟悉OpenGL顶点转换管道。
最后要明白,拥有一个"干净"的模型视图矩阵是没有意义的。您在第一个代码片段中所拥有的就是您想要的:一个可以在此基础上构建的基本矩阵。
更新
好吧,你的想法中有一个小误解:
glLoadIdentity();
// Pre-multiplication here as opposed to post-mulitplication in MV matrix
glTranslatef(400, 0);
glRotatef(yRotation, 0, 1, 0);
glTranslatef(-400, 0);
glFrustum(topLeftX, bottomRightX, bottomRightY, topLeftY, camNear, camFar);
是什么让你认为你应该在这里预乘?转换链是
p_view = MV · p_local
p_clip = P · p_view
你可以把它承包给
p_clip = P · MV · p_local
模型视图和投影矩阵的分离不是为了变换位置,而是为了变换法线。后面的步骤仅用于照明目的。但要使其工作,投影矩阵必须仅包含投影部分,而不包含任何视口位置。或者换句话说,这个glTranslate→glRotate→glTranslate部分不属于那里。无论如何,如果你决定"哦,我不需要照明"(无论出于何种原因,你都必须将其放置在对glFustum的调用之后。为什么?因为这就是为什么:
在第一种情况下,您的模型视图MV和投影p矩阵是
MV = I · gluLookAt · glTranslate · glRotate · glTranslate
P = I · glFrustum
由于I · x = x
,我们可以省略I。因此位置变换将是
v_clip = P · MV · v_local =
= glFrustum · gluLookAt · glTranslate · glRotate · glTranslate · glRotate · v_local
仅关于位置(而不是法线),可以将模型视图和投影变换之间的分割放置在上述变换链中的任何点上。在你想要的情况下(BTW没有多大意义),它就在*v_local*之前。所以
P = glFrustum · gluLookAt · glTranslate · glRotate · glTranslate · glRotate
但正如我已经说过的:只有在不需要正确变换法线的情况下,这才有效。
- 不计算一个范围内的完美数
- MacOS 上的 Xcode 11 项目不在一个函数中使用 sin 和 cos:未定义的符号"___sincosf_stret"
- 选择一个元素而不是一个对象的数组的原因
- 插件:TypeError:addons.function() 不是一个函数
- 如果我们不创建一个新节点并使用指针插入数据并建立链接(在链表中)怎么办?
- 只要我不包含一个标题,重新定义C++关键字合法吗
- std::shared_ptr 和 std::unique_ptr 构造函数之间的不对称
- 离散分布不对称
- 你怎么编码,如果x不等于一个数字,程序就会退出
- C++,当函子不是一个选项时,我如何编写带有自定义函数调用的模板化 RAII 包装器?
- 如何让这个C++代码从用户那里读取五个整数而不是一个整数?
- 将字符指针按顺序存储在 map 中 std::map<char*, int> mymap。将其存储为字符或字符串不是一个选项
- makefile不更新一个特定文件
- 为什么即将到来的范围库不支持一个范围的容器初始化
- 为什么我的运算符=(T&&)模板只绑定到一个const&而不是一个&&?
- 两个 4 位位字段加起来不等于一个字节的大小 - 如何修复?
- 为什么 std::list::splice 不是一个免费函数?
- 如果矩阵密集且不对称,特征库矩阵/矢量操作是否比 .net 矩阵/向量操作更快?
- 与不包括一个标头更好的使用不完整的标头比另一个标头的使用无效
- 旋转一个不对称的截头体