如何在Haskell OpenGL中应用非旋转正交归一3x3矩阵变换?
如何在Haskell OpenGL中应用非旋转正交归一3x3矩阵变换?
你现在已经能用Haskell OpenGL的基础变换函数(translate、rotate、scale)配合preservingMatrix来处理物体变换了,比如这段代码:
preservingMatrix $ do translate myvector renderObject Solid $ Sphere' 0.2 50 50
针对你想直接应用非旋转正交归一3x3矩阵M的需求,答案是完全可行的,而且不需要非得先分解成平移+旋转变换(当然分解的路子也能走,不过直接操作矩阵更直接)。
直接应用自定义矩阵的方法
OpenGL的变换本质是通过修改当前模型视图矩阵栈实现的,Haskell OpenGL提供了multMatrix函数,允许你直接把自定义的4x4齐次矩阵乘到当前矩阵上。因为你用的是3x3矩阵,需要先把它扩展成符合OpenGL要求的4x4齐次矩阵:
- 对于正交归一的3x3矩阵M,扩展后的4x4矩阵,前3行的前3列就是M的元素;
- 前3行的第4列填0(如果不需要额外平移的话);
- 最后一行固定为
[0, 0, 0, 1],保证齐次坐标的正确性。
举个具体的代码例子:
假设你的3x3矩阵M是:
[ m11 m12 m13 m21 m22 m23 m31 m32 m33 ]
那么对应的4x4矩阵可以这样构造:
import Graphics.Rendering.OpenGL (Matrix4(..), Vector4(..), multMatrix) -- 构造4x4齐次变换矩阵 let customMat = Matrix4 (Vector4 m11 m12 m13 0) (Vector4 m21 m22 m23 0) (Vector4 m31 m32 m33 0) (Vector4 0 0 0 1)
然后在绘制代码里使用它:
preservingMatrix $ do multMatrix customMat -- 如果需要叠加平移,再加translate myvector即可 renderObject Solid $ Sphere' 0.2 50 50
关于分解方案的补充
你提到可以把M分解为平移和旋转变换,数学上确实可行——正交归一矩阵的行列式如果是1就是纯旋转,是-1的话就是旋转加反射。不过分解需要额外做矩阵分解计算(比如QR分解、特征分解),相比直接用multMatrix会麻烦一些,所以如果没有特殊需求,直接用自定义矩阵的方式更高效。
最后提醒一下:OpenGL和Haskell的Matrix4都是列主序存储的,所以构造矩阵的时候要注意元素的顺序对应正确哦~
内容的提问来源于stack exchange,提问作者Stéphane Laurent
相关产品推荐
相关产品推荐

