我一直在开发游戏引擎,最近我可以轻松地创建一个Camera类来管理视图矩阵(或允许轻松切换到另一个)。我从概念上知道它必须做什么,但我遇到的问题是弄清楚如何绕局部原点旋转(对于视图矩阵,它与乘以旋转矩阵的平移矩阵相同)。
我知道在直接模式下,你会
glTranslatef(x, y, z); //move back to origin
glRotatef(angle, x_rot, y_rot, z_rot); //turn using a quaternion
glTranslatef(-x, -y, -z); //move back to original location
但我不确定这将如何转化为更现代的应用程序。你会做本质上相同的事情吗,让一个平移矩阵回到原点,旋转,然后平移回来?对于每一个要旋转的对象?根据我迄今为止的测试,这种方法适用于观看,但在3D空间中控制它很难(我不知道如何不断调整旋转。将运动分量转换为单个vec4,乘以旋转,应用于平移,然后进行实际旋转?)
似乎有一种比我错过的三次或三次以上的4x4矩阵乘法更有效的方法。
以下是在尝试了一个建议的解决方案后的具体部分。
您可以执行与发布的序列基本相同的操作,而无需在运行时执行全矩阵乘法。由于平移矩阵非常简单,所以可以手动进行乘法运算。R
是一个3x3旋转矩阵,p
是你想要旋转的位置,你可以通过以下方式构建你的4x4矩阵:
- 将
R
存储在4x4矩阵的旋转部分中 - 计算
p - R * p
,并将结果存储在4x4矩阵的平移部分
这将把它简化为一个矩阵*向量乘和一个向量减法。你可能想仔细检查一下我的数学,因为我只是从纸上推导出来的。
另一种方法是,在CPU代码中保持旋转和平移分离,根据需要进行更新,并且在更新统一时仅将它们组合成4x4矩阵。
由于您可以控制着色器代码,因此甚至不必使用4x4矩阵来包含整个变换。例如,如果在旋转之前应用平移更方便,可以将mat3旋转矩阵和vec3平移向量输入到着色器中,并在与旋转矩阵相乘之前将平移向量添加到该位置。如果你更频繁地更新其中一个,那么将两者分开也是有益的。
我认为您考虑旧的管道会使它过于复杂。
形成你的新变换矩阵T。假设你有你现有的相机矩阵C。你想要C’,修改后的相机矩阵。
实际上只有两种选择。任一:
C' = CT, or
C' = TC
因为你还有什么其他信息?
在实践中,你要选择的是在现有相机矩阵"之前"发生的新变换,在这种情况下,它将在世界坐标中发生,或者在"之后"发生,在这种情形下,它会在相机坐标中发生。
你似乎想要预乘法。那就用它吧。然后,变换将在全局坐标空间中生效。
旧的OpenGL例程总是后相乘。