После перевода форма не вращается вокруг своего происхождения - PullRequest
0 голосов
/ 12 ноября 2018

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

Масштабирование и вращение идеально работают без перевода.Но когда я применяю перевод к объекту и пытаюсь повернуть его снова - он вращается вокруг источника мира.

Я знаю, что операции преобразования должны происходить в следующем порядке: масштабирование -> вращение -> перевод.Но я не понимаю, как это сделать только с одной матрицей (моделью).

Итак, как мне сделать это правильно?Должен ли я использовать 3 матрицы?

Моя работа с матрицами:

        for (int i = 0; i < vertices.Count; ++i)
        {
            float[,] vertexCoords = { { vertices[i].SX }, { vertices[i].SY }, { vertices[i].SZ }, { vertices[i].SW } };

            var modelViewMatrix = MatrixMultiplier.MultiplyMatrix(camera.ViewMatrix, shape.ModelMatrix);
            var eyeCoordinates = MatrixMultiplier.MultiplyMatrix(modelViewMatrix, vertexCoords);
            var clipCoordinates = MatrixMultiplier.MultiplyMatrix(camera.ProjectionMatrix, eyeCoordinates);


            var ndc = new float[,] {
                { clipCoordinates[0, 0] / clipCoordinates[3, 0] },
                { clipCoordinates[1, 0] / clipCoordinates[3, 0] },
                { clipCoordinates[2, 0] / clipCoordinates[3, 0] },
                { clipCoordinates[3, 0]}
            };

            var windowCoordinates = new float[,] { 
                { 640 / 2 * ndc[0, 0] + (640 / 2) },
                { 360 / 2 * ndc[1, 0] + (360 / 2) },
                { (50 - (-50)) / 2 * ndc[2, 0] + (50 + (-50)) / 2 },
                { ndc[3, 0]}
            };

            SetNewCoordinatesToPoint(vertices[i], windowCoordinates);             
        }

Пример алгоритма вращения:

private void RotateZ(MCommonPrimitive shape, double angle)
    {
        double rads = angle * Math.PI / 180.0;

        float[,] rotateZ = {
            { (float)Math.Cos(rads), -(float)Math.Sin(rads), 0, 0 },
            { (float)Math.Sin(rads), (float)Math.Cos(rads), 0, 0 },
            { 0, 0, 1, 0 },
            { 0, 0, 0, 1 }
        };

        shape.ModelMatrix = MatrixMultiplier.MultiplyMatrix(rotateZ, shape.ModelMatrix);
    }

MatrixMultiplier:

public static class MatrixMultiplier
{
    public static float[,] MultiplyMatrix(float[,] a, float[,] b)
    {
        float[,] c = null;

        if (a.GetLength(1) == b.GetLength(0))
        {
            c = new float[a.GetLength(0), b.GetLength(1)];
            for (int i = 0; i < c.GetLength(0); i++)
            {
                for (int j = 0; j < c.GetLength(1); j++)
                {
                    c[i, j] = 0;
                    for (int k = 0; k < a.GetLength(1); k++) // OR k<b.GetLength(0)
                        c[i, j] = c[i, j] + a[i, k] * b[k, j];
                }
            }
        }
        else
        {
            Console.WriteLine("\n Number of columns in First Matrix should be equal to Number of rows in Second Matrix.");
            Console.WriteLine("\n Please re-enter correct dimensions.");
            throw new ArithmeticException("Number of columns in First Matrix should be equal to Number of rows in Second Matrix");
        }

        return c;
    }
}

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Но когда я применяю перевод к объекту и пытаюсь повернуть его снова - он вращается вокруг источника мира.

Да, вот как это работает. Сначала необходимо повернуть объект, а затем перевести его в нужное положение. Геометрические преобразования не являются коммутативными, т. Е. Порядок операций имеет значение.

0 голосов
/ 13 ноября 2018

Согласно оригинальному ответу Нико Шертлера все зависит от порядка умножения матриц.Так, например, если я буду использовать этот код

shape.ModelMatrix = MatrixMultiplier.MultiplyMatrix(rotateZ, shape.ModelMatrix);

из моего метода RotateZ, форма будет вращаться вокруг мирового происхождения.И, если я изменю свой код на это:

shape.ModelMatrix = MatrixMultiplier.MultiplyMatrix(shape.ModelMatrix, rotateZ);

форма будет вращаться вокруг своего центра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...