Применение матрицы моделирования для просмотра матрицы = сбой

#c# #opengl #3d #opentk

#c# #opengl #3D #opentk

Вопрос:

У меня проблема с перемещением и вращением объектов в OpenGL. Я использую C # и OpenTK (Mono), но, думаю, проблема в том, что я не понимаю часть OpenGL, поэтому вы могли бы мне помочь, даже если вы ничего не знаете о C # / OpenTK.

Я читаю супербиблиотеку OpenGL (последняя версия) и попытался переписать GLFrame на C #. Вот часть, которую я уже переписал:

 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() , он работает (второй снимок экрана). Однако, если я не использую эти два метода и передаю матрицу моделирования непосредственно в OpenGL GL.MultMatrix() , она рисует что-то странное (первый снимок экрана).

Как это выглядит
Как это должно выглядеть

Можете ли вы мне помочь и объяснить, в чем проблема? Почему это работает с использованием методов перевода и поворота, но не с умножением матрицы представления на матрицу моделирования?

Комментарии:

1. Просто догадка — попробуйте использовать транспонирование матрицы преобразования, которую вы используете.

2. Ты что, бог? Это сработало! Спасибо!

3. Я так не думаю… Это просто хорошая практика, чтобы проверить это, прежде чем углубляться в код gl. Я напишу это как ответ (пожалуйста, примите).

4. @TalDarom, если кто-то спросит тебя, бог ли ты, скажи «ДА»! 1.

5. <strike> Я так не думаю …</strike> Да! Это просто хорошая практика, чтобы <strike> проверить это, прежде чем углубляться в код gl. Я напишу это как ответ (пожалуйста, примите). </strike> преклони колени перед своим мастером! @BrettHale, лучше?

Ответ №1:

Матрицы преобразования OpenGL упорядочены по столбцам. Вы должны использовать транспонирование используемой матрицы.