【问题标题】:Can't identify error in my matrix calculation?无法识别我的矩阵计算中的错误?
【发布时间】:2014-07-07 22:45:03
【问题描述】:

所以,我尝试在 OpenTK 中使用矩阵,我的“变换”类有一个 Rotation(四元数)和一个 Vector3 作为位置。它提供以下领域:

    public virtual Vector3 Right
    {
        get
        {
            
            return Vector3.Transform(Vector3.UnitX, Rotation);
        }
    }
    public virtual Vector3 Forward
    {
        get 
        {
            return Vector3.Transform(-Vector3.UnitZ, Rotation);
        }
    }
    public virtual Vector3 Up
    {
        get
        {
            return Vector3.Transform(Vector3.UnitY, Rotation);
        }
    }

这就是创建视图和模型矩阵的方式:

    public virtual Matrix4 GetMatrix()
    {
        Matrix4 translation = Matrix4.CreateTranslation(Position);
        Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
        return translation * rotation;
    }

投影:

    private void SetupProjection()
    {
        if(GameObject != null)
        {
            AspectRatio = GameObject.App.Window.Width / (float)GameObject.App.Window.Height;
            projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)((Math.PI * Fov) / 180), AspectRatio, ZNear, ZFar);
            
        }
    }

矩阵乘法:

    public Matrix4 GetModelViewProjectionMatrix(Transform model)
    {
        return  model.GetMatrix()* Transform.GetMatrix() * projectionMatrix;
    }

着色器:

[Shader vertex]
#version 150 core

in vec3 pos;
in vec4 color;
uniform float _time;
uniform mat4 _modelViewProjection;

out vec4 vColor;

void main() {
    gl_Position = _modelViewProjection * vec4(pos, 1);
    vColor = color;
}

OpenTK 矩阵是转置的,因此是乘法顺序。

此设置的问题在于,所有轴和方向向量以及对象位置都被混合、镜像和颠倒。

现在经过大量的摆弄,我设法得到了一个有用的转换,最终得到了以下结果:

我必须反转四元数的方向:

    public virtual Vector3 Right
    {
        get
        {
            
            return Vector3.Transform(Vector3.UnitX, Rotation.Inverted());
        }
    }
    public virtual Vector3 Forward
    {
        get
        {
            return Vector3.Transform(-Vector3.UnitZ, Rotation.Inverted());
        }
    }
    public virtual Vector3 Up
    {
        get
        {
            return Vector3.Transform(Vector3.UnitY, Rotation.Inverted());
        }
    }

我不得不像这样修改视图矩阵结构:

    public virtual Matrix4 GetMatrixView()
    {
        Matrix4 translation = Matrix4.CreateTranslation(Position*2).Inverted();
        Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
        return translation * rotation;
    }

如您所见,我必须反转平移矩阵并将位置乘以 2,以使相机空间与世界空间匹配。什么F?

编辑:看看这个。使用默认/直觉设置,我得到了这个:

[日志]: (0; 0; 10) ->

[日志]: FW(0; 0; -1)

[LOG]: R(-1; 0; 0)

[日志]:上升(0;1;0)

好的,我在 Z 10,看着 0,0,0。正如预期的那样,前向是 x -1。向上是Y 1,也可以。但是水平轴向左?这是什么坐标系?

【问题讨论】:

  • 您的 Position、Rotation、ZNear 和 ZFar 的值是多少?
  • znear 是 1,zfar 是 120。位置和旋转是可变的。但在启动位置和旋转分别是标识和零。
  • 零旋转,所以是Quaternion.Identity?否则很奇怪,有了 MV 矩阵的标识,你的模型应该在任何地方渲染。顺便说一句,你在做translation * rotation,你确定要先翻译再旋转吗?
  • 嗯,我想通过它的位置平移对象,然后通过它的旋转旋转?!否则我会旋转翻译。 PS:是的,轮换就是身份
  • 我的意思是,例如,如果您从 (0,0,0) 开始,平移 (-10,0,0),围绕 Z 轴旋转 90 度,您的对象将位于 (0,0,10)。如果先旋转然后平移,您的对象将围绕其中心旋转,然后平移到 (-10,0,0)。因此,根据变换的顺序,它最终会出现在不同的位置。

标签: opengl matrix rotation quaternions opentk


【解决方案1】:

您提到矩阵是转置的,因此为什么乘法顺序是相反的。例如,您的 MVP 计算是:

model.GetMatrix()* Transform.GetMatrix() * projectionMatrix;

但是您的翻译 * 旋转连接顺序错误:

Matrix4 translation = Matrix4.CreateTranslation(Position);
Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
return translation * rotation;

对于非转置矩阵,正确的乘法顺序是:

translation * rotation * scale

所以对于你的转置矩阵,它应该被反转为:

scale * rotation * translation

所以你的代码应该是:

Matrix4 translation = Matrix4.CreateTranslation(Position);
Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
return rotation * translation;

【讨论】:

  • 这会导致相机绕0,0坐标转
  • GetMatrixView() 是否应该返回一个视图矩阵?
  • 是的。但是视图矩阵不应该像网格的模型矩阵一样计算吗?
  • 没有视图矩阵的组装方式不同,这里有一个很好的链接可以查看:3dgep.com/understanding-the-view-matrix
  • 好的,尽管该教程使用了行主矩阵,但它有所帮助。但是现在当我尝试围绕局部轴旋转相机矩阵(无视图)时,旋转都搞砸了!我执行以下操作来展示视图:LocalRotation *= Quaternion.FromAxisAngle(axis, angle); 使用轴 Vector3.Transform(Vector3.UnitX, Rotation)。那应该是局部右向量吗?
猜你喜欢
  • 2021-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 2019-12-05
  • 1970-01-01
相关资源
最近更新 更多