将建模矩阵应用于视图矩阵=失败

发布于 2024-12-12 16:49:45 字数 3163 浏览 0 评论 0原文

我在 OpenGL 中移动和旋转对象时遇到问题。我正在使用 C# 和 OpenTK (Mono),但我想问题是我不理解 OpenGL 部分,所以即使您对 C# / OpenTK 一无所知,您也可以帮助我。

我正在阅读 OpenGL SuperBible(最新版),并尝试重写 C# 中的 GLFrame。这是我已经重写的部分:

public class GameObject
{
    protected Vector3 vLocation;
    public Vector3 vUp;
    protected Vector3 vForward;

    public GameObject(float x, float y, float z)
    {
        vLocation = new Vector3(x, y, z);
        vUp = Vector3.UnitY;
        vForward = Vector3.UnitZ;
    }

    public Matrix4 GetMatrix(bool rotationOnly = false)
    {
        Matrix4 matrix;

        Vector3 vXAxis;
        Vector3.Cross(ref vUp, ref vForward, out vXAxis);

        matrix = new Matrix4();
        matrix.Row0 = new Vector4(vXAxis.X, vUp.X, vForward.X, vLocation.X);
        matrix.Row1 = new Vector4(vXAxis.Y, vUp.Y, vForward.Y, vLocation.Y);
        matrix.Row2 = new Vector4(vXAxis.Z, vUp.Z, vForward.Z, vLocation.Z);
        matrix.Row3 = new Vector4(0.0f, 0.0f, 0.0f, 1.0f);

        return matrix;
    }

    public void Move(float x, float y, float z)
    {
        vLocation = new Vector3(x, y, z);
    }

    public void RotateLocalZ(float angle)
    {
        Matrix4 rotMat;

        // Just Rotate around the up vector
        // Create a rotation matrix around my Up (Y) vector
        rotMat = Matrix4.CreateFromAxisAngle(vForward, angle);

        Vector3 newVect;

        // Rotate forward pointing vector (inlined 3x3 transform)
        newVect.X = rotMat.M11 * vUp.X + rotMat.M12 * vUp.Y + rotMat.M13 * vUp.Z;
        newVect.Y = rotMat.M21 * vUp.X + rotMat.M22 * vUp.Y + rotMat.M23 * vUp.Z;
        newVect.Z = rotMat.M31 * vUp.X + rotMat.M32 * vUp.Y + rotMat.M33 * vUp.Z;

        vUp = newVect;
    }
}

因此,我在一些随机坐标上创建一个新的 GameObject (GLFrame): GameObject go = new GameObject(0, 0, 5); 并稍微旋转它: go.RotateLocalZ(rotZ);。然后我使用 Matrix4 matrix = go.GetMatrix(); 获取矩阵并渲染帧(首先,我设置查看矩阵,然后将其与建模矩阵相乘)

protected override void OnRenderFrame(FrameEventArgs e)
{
    base.OnRenderFrame(e);
    this.Title = "FPS: " + (1 / e.Time).ToString("0.0");

    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadIdentity();

    Matrix4 modelmatrix = go.GetMatrix();
    Matrix4 viewmatrix = Matrix4.LookAt(new Vector3(5, 5, -10), Vector3.Zero, Vector3.UnitY);

    GL.LoadMatrix(ref viewmatrix);

    GL.MultMatrix(ref modelmatrix);

    DrawCube(new float[] { 0.5f, 0.4f, 0.5f, 0.8f });

    SwapBuffers();
}

DrawCube(float[ ] color) 是我自己绘制立方体的方法。

现在是最重要的部分:如果我渲染帧没有 GL.MultMatrix(ref matrix); 部分,但是使用 GL .Translate()GL.Rotate(),它可以工作(第二个屏幕截图)。但是,如果我不使用这两种方法,而是使用 GL.MultMatrix() 直接将建模矩阵传递给 OpenGL,则会绘制一些奇怪的内容(第一个屏幕截图)。

看起来怎么样 它应该是什么样子

你能帮我解释一下问题出在哪里吗?为什么它可以使用平移和旋转方法工作,但不能使用视图矩阵乘以建模矩阵?

I've got a problem with moving and rotating objects in OpenGL. I'm using C# and OpenTK (Mono), but I guess the problem is with me not understanding the OpenGL part, so you might be able to help me even if you don't know anything about C# / OpenTK.

I'm reading the OpenGL SuperBible (latest edition) and I tried to rewrite the GLFrame in C#. Here is the part I've already rewritten:

public class GameObject
{
    protected Vector3 vLocation;
    public Vector3 vUp;
    protected Vector3 vForward;

    public GameObject(float x, float y, float z)
    {
        vLocation = new Vector3(x, y, z);
        vUp = Vector3.UnitY;
        vForward = Vector3.UnitZ;
    }

    public Matrix4 GetMatrix(bool rotationOnly = false)
    {
        Matrix4 matrix;

        Vector3 vXAxis;
        Vector3.Cross(ref vUp, ref vForward, out vXAxis);

        matrix = new Matrix4();
        matrix.Row0 = new Vector4(vXAxis.X, vUp.X, vForward.X, vLocation.X);
        matrix.Row1 = new Vector4(vXAxis.Y, vUp.Y, vForward.Y, vLocation.Y);
        matrix.Row2 = new Vector4(vXAxis.Z, vUp.Z, vForward.Z, vLocation.Z);
        matrix.Row3 = new Vector4(0.0f, 0.0f, 0.0f, 1.0f);

        return matrix;
    }

    public void Move(float x, float y, float z)
    {
        vLocation = new Vector3(x, y, z);
    }

    public void RotateLocalZ(float angle)
    {
        Matrix4 rotMat;

        // Just Rotate around the up vector
        // Create a rotation matrix around my Up (Y) vector
        rotMat = Matrix4.CreateFromAxisAngle(vForward, angle);

        Vector3 newVect;

        // Rotate forward pointing vector (inlined 3x3 transform)
        newVect.X = rotMat.M11 * vUp.X + rotMat.M12 * vUp.Y + rotMat.M13 * vUp.Z;
        newVect.Y = rotMat.M21 * vUp.X + rotMat.M22 * vUp.Y + rotMat.M23 * vUp.Z;
        newVect.Z = rotMat.M31 * vUp.X + rotMat.M32 * vUp.Y + rotMat.M33 * vUp.Z;

        vUp = newVect;
    }
}

So I create a new GameObject (GLFrame) on some random coordinates: GameObject go = new GameObject(0, 0, 5); and rotate it a bit: go.RotateLocalZ(rotZ);. Then I get the matrix using Matrix4 matrix = go.GetMatrix(); and render frame (first, I set the viewing matrix and then I multiply it with modeling matrix)

protected override void OnRenderFrame(FrameEventArgs e)
{
    base.OnRenderFrame(e);
    this.Title = "FPS: " + (1 / e.Time).ToString("0.0");

    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadIdentity();

    Matrix4 modelmatrix = go.GetMatrix();
    Matrix4 viewmatrix = Matrix4.LookAt(new Vector3(5, 5, -10), Vector3.Zero, Vector3.UnitY);

    GL.LoadMatrix(ref viewmatrix);

    GL.MultMatrix(ref modelmatrix);

    DrawCube(new float[] { 0.5f, 0.4f, 0.5f, 0.8f });

    SwapBuffers();
}

The DrawCube(float[] color) is my own method for drawing a cube.

Now the most important part: If I render the frame without the GL.MultMatrix(ref matrix); part, but using GL.Translate() and GL.Rotate(), it works (second screenshot). However, if I don't use these two methods and I pass the modeling matrix directly to OpenGL using GL.MultMatrix(), it draws something strange (first screenshot).

How it looks like
How it should look like

Can you help me and explain me where is the problem? Why does it work using translate and rotate methods, but not with multiplying the view matrix by the modeling matrix?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

伤感在游骋 2024-12-19 16:49:48

OpenGL 变换矩阵按列排序。您应该使用您正在使用的矩阵的转置。

OpenGL transformation matrices are ordered column wise. You should use the transpose of the matrix you are using.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文