Форум программистов, компьютерный форум CyberForum.ru

Объединение view и projection матриц - C++

Восстановить пароль Регистрация
 
 
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
19.09.2016, 11:45     Объединение view и projection матриц #1
Здравствуйте!

Извиняюсь заранее, если "не туда" пишу, тут много разделов, выбирал между "математикой" и "играми".

Если издалека, то чтобы обработать вертексы, мы их пропускаем через transformation матрицу. Она состоит из трёх: translation, rotation и scaling. Тут есть два варианта перемножения. Либо перемножить матрицы в одну, а потом пропускать вертексы через неё либо пропустить вертексы сначала через translation матрицу, потом то, что получится через rotation и потом результат пропустить ещё и через scaling. Я провёл несколько подсчётов и убедился, что первый вариант быстрее (если в объекте больше четырёх вертексов, что почти всегда и бывает).

Дальше мы пропускаем вертексы через view и projection матрицы. И тут, я тоже подумал: "окей, вместо того чтобы перемножать вертексы на view матрицу, и потом снова новые вертексы перемножать на projection матрицу, лучше я их объединю в viewProjection матрицу и пропущу вертексы через неё".
Здесь и появляется проблема. Моя projection матрица является перспективной. А view матрица имеет перемещение по оси z (0.0f, 0.0f, 15.0f), (view матрицу мы инверсируем, в итоге получаем -15.0f). И дело в том, что я получаю разные результаты: если я сначала перемножаю вертексы на view матрицу, а потом получившиеся перемножаю на projection матрицу, то всё работает. А если я сначала перемножаю эти две матрицы и перемножаю вертексы на viewProjection матрицу, то получается... да вообще ничего не получается. Там компонента z и w совсем другая становится.

Вы не подскажете, это у меня проблема в вычислениях где-то, потому что всё должно работать одинаково независимо от метода перемножения или это известная проблема, которая не лечится и в связи с этим перемножать матрицы в одну нельзя в принципе.

Я пока код решил не скидывать, так как пока вопрос теоретический. Но, если нужен будет, то всё выложу и подробно расскажу.

Заранее спасибо.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
TanaTiX
Модератор
 Аватар для TanaTiX
2731 / 1576 / 144
Регистрация: 19.02.2011
Сообщений: 5,658
19.09.2016, 17:43     Объединение view и projection матриц #2
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Я пока код решил не скидывать
Код на чем пишется?
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
19.09.2016, 18:23  [ТС]     Объединение view и projection матриц #3
Цитата Сообщение от TanaTiX Посмотреть сообщение
Код на чем пишется?
С++
Скинуть?
TanaTiX
Модератор
 Аватар для TanaTiX
2731 / 1576 / 144
Регистрация: 19.02.2011
Сообщений: 5,658
19.09.2016, 18:52     Объединение view и projection матриц #4
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Скинуть?
Нет, туда сейчас тема переедет. В 3D-моделировании ей явно не место. Хотя наверняка там попросят код, так что скинуть лишним не будет.
Fulcrum_013
 Аватар для Fulcrum_013
497 / 613 / 68
Регистрация: 14.12.2014
Сообщений: 4,949
Завершенные тесты: 2
19.09.2016, 19:14     Объединение view и projection матриц #5
Цитата Сообщение от Pro100Tom Посмотреть сообщение
А если я сначала перемножаю эти две матрицы и перемножаю вертексы на viewProjection матрицу, то получается... да вообще ничего не получается. Там компонента z и w совсем другая становится.
Если сами матрицы построены правильно и правильно работает перемножение то все там получается. Причем произведение всех трех сразу Model*View*Projection. Именно в таком порядке. При этом обычно еще хранят произведение View*Projection потому как оно меняется обычно раз в кадр а Model меняется на каждый объект, поэтому перемножают Model * ViewProjection для экономии матричных умножений при переходе от объекта к объекту.

Добавлено через 3 минуты
Цитата Сообщение от Pro100Tom Посмотреть сообщение
view матрицу мы инверсируем, в итоге получаем -15.0f
Зачем ее инвертировать? Она при построении путем LookAt уже получается инвертированная.
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
19.09.2016, 19:18  [ТС]     Объединение view и projection матриц #6
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Зачем ее инвертировать?
CPU rendering, никаких дополнительных либ, всё ручками сделал, вплоть до алгоритма рисования и закрашивания треугольников.

Добавлено через 1 минуту
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если сами матрицы построены правильно и правильно работает перемножение то все там получается.
Спасибо! Буду искать ошибку. Как вернусь с работы, скину весь проект и ключевые функции. Если кто сможет помочь найти ошибку, буду очень признателен.
Fulcrum_013
 Аватар для Fulcrum_013
497 / 613 / 68
Регистрация: 14.12.2014
Сообщений: 4,949
Завершенные тесты: 2
19.09.2016, 19:23     Объединение view и projection матриц #7
Цитата Сообщение от Pro100Tom Посмотреть сообщение
CPU rendering, никаких дополнительных либ, всё ручками сделал, вплоть до алгоритма рисования и закрашивания треугольников
Стоит поискать ошибку в умножении и формировании матриц.
У меня для того чтобы ошибок не было код операций между матрицами и векторами машинно-генерированный
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Если кто сможет помочь найти ошибку, буду очень признателен.
Скинь код построения матриц проекции и вида
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
19.09.2016, 20:38  [ТС]     Объединение view и projection матриц #8
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Points Renderer::ConvertToNDC(Vertex(&vertices)[3])
{
    Points points;
    
    for (int i = 0; i < 3; i++)
    {
        Vertex vertex = vertices[i] / vertices[i].w;
 
        Point point;
 
        point.x = (int)(vertex.x * horizontalScale + halfWidth);
        point.y = (int)(-vertex.y * verticalScale + halfHeight);
 
        points.push_back(point);
    }
 
    return points;
}
 
void Renderer::Render()
{
    Matrix4x4 viewMatrix = currentCamera.GetViewMatrix();
    Matrix4x4 projectonMatrix = currentCamera.GetProjectionMatrix();
 
    for (unsigned int j = 0; j < models.size(); j++)
    {
        Vertices tempVertices = viewMatrix * models[j].GetTransformedVertices();
        Vertices finalVertices = projectonMatrix * tempVertices;
 
        for (unsigned int i = 0; i < models[j].vertexFaces.size(); i++)
        {
            Face face = models[j].vertexFaces[i];
            Vertex polygonVertices[] =
            {
                finalVertices[face.a - 1],
                finalVertices[face.b - 1],
                finalVertices[face.c - 1]
            };
 
            Points points = ConvertToNDC(polygonVertices);
            DrawTriangle(points[0], points[1], points[2]);
        }
    }
}

C++
1
2
3
4
Vertex operator / (const Vertex& vertex, const float scalar)
{
    return Vertex(vertex.x / scalar, vertex.y / scalar, vertex.z / scalar);
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Matrix4x4 operator * (const Matrix4x4& firstMatrix, const Matrix4x4& secondMatrix)
{
    Matrix4x4 newMatrix = Matrix4x4();
 
    newMatrix.elements[0][0] = 
        firstMatrix.elements[0][0] * secondMatrix.elements[0][0] +
        firstMatrix.elements[0][1] * secondMatrix.elements[1][0] +
        firstMatrix.elements[0][2] * secondMatrix.elements[2][0] +
        firstMatrix.elements[0][3] * secondMatrix.elements[3][0];
 
    newMatrix.elements[0][1] =
        firstMatrix.elements[0][0] * secondMatrix.elements[0][1] +
        firstMatrix.elements[0][1] * secondMatrix.elements[1][1] +
        firstMatrix.elements[0][2] * secondMatrix.elements[2][1] +
        firstMatrix.elements[0][3] * secondMatrix.elements[3][1];
 
    newMatrix.elements[0][2] =
        firstMatrix.elements[0][0] * secondMatrix.elements[0][2] +
        firstMatrix.elements[0][1] * secondMatrix.elements[1][2] +
        firstMatrix.elements[0][2] * secondMatrix.elements[2][2] +
        firstMatrix.elements[0][3] * secondMatrix.elements[3][2];
 
    newMatrix.elements[0][3] =
        firstMatrix.elements[0][0] * secondMatrix.elements[0][3] +
        firstMatrix.elements[0][1] * secondMatrix.elements[1][3] +
        firstMatrix.elements[0][2] * secondMatrix.elements[2][3] +
        firstMatrix.elements[0][3] * secondMatrix.elements[3][3];
 
 
 
 
    newMatrix.elements[1][0] =
        firstMatrix.elements[1][0] * secondMatrix.elements[0][0] +
        firstMatrix.elements[1][1] * secondMatrix.elements[1][0] +
        firstMatrix.elements[1][2] * secondMatrix.elements[2][0] +
        firstMatrix.elements[1][3] * secondMatrix.elements[3][0];
 
    newMatrix.elements[1][1] =
        firstMatrix.elements[1][0] * secondMatrix.elements[0][1] +
        firstMatrix.elements[1][1] * secondMatrix.elements[1][1] +
        firstMatrix.elements[1][2] * secondMatrix.elements[2][1] +
        firstMatrix.elements[1][3] * secondMatrix.elements[3][1];
 
    newMatrix.elements[1][2] =
        firstMatrix.elements[1][0] * secondMatrix.elements[0][2] +
        firstMatrix.elements[1][1] * secondMatrix.elements[1][2] +
        firstMatrix.elements[1][2] * secondMatrix.elements[2][2] +
        firstMatrix.elements[1][3] * secondMatrix.elements[3][2];
 
    newMatrix.elements[1][3] =
        firstMatrix.elements[1][0] * secondMatrix.elements[0][3] +
        firstMatrix.elements[1][1] * secondMatrix.elements[1][3] +
        firstMatrix.elements[1][2] * secondMatrix.elements[2][3] +
        firstMatrix.elements[1][3] * secondMatrix.elements[3][3];
 
 
 
 
 
 
 
 
    newMatrix.elements[2][0] =
        firstMatrix.elements[2][0] * secondMatrix.elements[0][0] +
        firstMatrix.elements[2][1] * secondMatrix.elements[1][0] +
        firstMatrix.elements[2][2] * secondMatrix.elements[2][0] +
        firstMatrix.elements[2][3] * secondMatrix.elements[3][0];
 
    newMatrix.elements[2][1] =
        firstMatrix.elements[2][0] * secondMatrix.elements[0][1] +
        firstMatrix.elements[2][1] * secondMatrix.elements[1][1] +
        firstMatrix.elements[2][2] * secondMatrix.elements[2][1] +
        firstMatrix.elements[2][3] * secondMatrix.elements[3][1];
 
    newMatrix.elements[2][2] =
        firstMatrix.elements[2][0] * secondMatrix.elements[0][2] +
        firstMatrix.elements[2][1] * secondMatrix.elements[1][2] +
        firstMatrix.elements[2][2] * secondMatrix.elements[2][2] +
        firstMatrix.elements[2][3] * secondMatrix.elements[3][2];
 
    newMatrix.elements[2][3] =
        firstMatrix.elements[2][0] * secondMatrix.elements[0][3] +
        firstMatrix.elements[2][1] * secondMatrix.elements[1][3] +
        firstMatrix.elements[2][2] * secondMatrix.elements[2][3] +
        firstMatrix.elements[2][3] * secondMatrix.elements[3][3];
 
 
 
 
 
 
    newMatrix.elements[3][0] =
        firstMatrix.elements[3][0] * secondMatrix.elements[0][0] +
        firstMatrix.elements[3][1] * secondMatrix.elements[1][0] +
        firstMatrix.elements[3][2] * secondMatrix.elements[2][0] +
        firstMatrix.elements[3][3] * secondMatrix.elements[3][0];
 
    newMatrix.elements[3][1] =
        firstMatrix.elements[3][0] * secondMatrix.elements[0][1] +
        firstMatrix.elements[3][1] * secondMatrix.elements[1][1] +
        firstMatrix.elements[3][2] * secondMatrix.elements[2][1] +
        firstMatrix.elements[3][3] * secondMatrix.elements[3][1];
 
    newMatrix.elements[3][2] =
        firstMatrix.elements[3][0] * secondMatrix.elements[0][2] +
        firstMatrix.elements[3][1] * secondMatrix.elements[1][2] +
        firstMatrix.elements[3][2] * secondMatrix.elements[2][2] +
        firstMatrix.elements[3][3] * secondMatrix.elements[3][2];
 
    newMatrix.elements[3][3] =
        firstMatrix.elements[3][0] * secondMatrix.elements[0][3] +
        firstMatrix.elements[3][1] * secondMatrix.elements[1][3] +
        firstMatrix.elements[3][2] * secondMatrix.elements[2][3] +
        firstMatrix.elements[3][3] * secondMatrix.elements[3][3];
 
 
    /*for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            newMatrix.elements[i][j] =
                firstMatrix.elements[i][0] * secondMatrix.elements[0][j] +
                firstMatrix.elements[i][1] * secondMatrix.elements[1][j] +
                firstMatrix.elements[i][2] * secondMatrix.elements[2][j] +
                firstMatrix.elements[i][3] * secondMatrix.elements[3][j];
        }
    }*/
 
    return newMatrix;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
Vertices operator * (const Matrix4x4& matrix, const Vertices vertices)
{
    std::vector<Vertex> newVertices;
 
    for (unsigned int i = 0; i < vertices.size(); i++)
    {
        Vertex vertex = matrix * vertices[i];
        newVertices.push_back(vertex);
    }
 
    return newVertices;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
bool BaseModel::BuildTransformationMatrix()
{
    bool changesWereMade = false;
 
    if (isTranslateRotateOutdated)
    {
        // Set translation values into translation matrix
        translationMatrix.elements[0][3] = location.x;
        translationMatrix.elements[1][3] = location.y;
        translationMatrix.elements[2][3] = location.z;
 
 
        // Prepare values and set them into rotation matrix
        float angleDeg = rotationAngle.y * Math::pi / 180.0f;
        rotationMatrix.elements[0][0] = rotationMatrix.elements[2][2] = cos(angleDeg);
 
        float result = sin(angleDeg);
        rotationMatrix.elements[0][2] = result;
        rotationMatrix.elements[2][0] = -result;
 
 
        translationRotationMatrix = translationMatrix * rotationMatrix;
        isTranslateRotateOutdated = false;
 
        changesWereMade = true;
    }
 
    if (isScaleOutdated)
    {
        // Set scale values into scaling matrix
        scalingMatrix.elements[0][0] = scale.x;
        scalingMatrix.elements[1][1] = scale.y;
        scalingMatrix.elements[2][2] = scale.z;
 
        transformationMatrix = translationRotationMatrix * scalingMatrix;
        isScaleOutdated = false;
 
        changesWereMade = true;
    }
 
    return changesWereMade;
}
C++
1
2
3
4
5
6
7
8
9
10
11
Camera::Camera()
{
    Math::Identity(viewMatrix);
    Math::Identity(projectionMatrix);
    projectionMatrix.elements[2][3] = -1.0f;
    projectionMatrix.elements[3][3] = 0.0f;
 
    SetNearFar(-1.0f, 1.0f);
    SetFov(10.0f);
    SetEye(Vertex(0.0f, 0.0f, 15.0f));
}

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void Camera::BuildProjectionMatrix()
{
    if (isProjectionOutdated)
    {
        float scale = 1 / (tanf(fov / 2 * Math::pi / 180.0f));
        projectionMatrix.elements[0][0] = projectionMatrix.elements[1][1] = scale;
 
        float difference = farPlane - nearPlane;
        projectionMatrix.elements[2][2] = -(farPlane / difference);
        projectionMatrix.elements[3][2] = -(farPlane * nearPlane / difference);
        isProjectionOutdated = false;
    }
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
float Math::CalculateDeterminant(const Matrix3x3& matrix)
{
    return matrix.elements[0][0] * (matrix.elements[1][1] * matrix.elements[2][2] - matrix.elements[1][2] * matrix.elements[2][1]) -
        matrix.elements[0][1] * (matrix.elements[1][0] * matrix.elements[2][2] - matrix.elements[1][2] * matrix.elements[2][0]) +
        matrix.elements[0][2] * (matrix.elements[1][0] * matrix.elements[2][1] - matrix.elements[1][1] * matrix.elements[2][0]);
}
 
 
float Math::CalculateDeterminant(const Matrix4x4& matrix)
{
    std::vector<int> horizontalIndexes = { 1, 2, 3 };
    float det = 0.0f;
 
    for (int j = 0; j < 4; j++)
    {
        if (matrix.elements[0][j] == 0) { continue; }
 
        std::vector<int> verticalIndexes = { 0, 1, 2, 3 };
        std::vector<int>::iterator vPosition = std::find(verticalIndexes.begin(), verticalIndexes.end(), j);
        verticalIndexes.erase(vPosition);
 
        Matrix3x3 tempMatrix;
        for (int k = 0; k < 3; k++)
        {
            for (int l = 0; l < 3; l++)
            {
                tempMatrix.elements[k][l] = matrix.elements[horizontalIndexes[k]][verticalIndexes[l]];
            }
        }
 
        int sign = j % 2 ? -1 : 1;
 
        det += matrix.elements[0][j] * CalculateDeterminant(tempMatrix) * sign;
    }
 
    return det;
}
 
 
void Math::TransposeMatrix(const Matrix4x4& inputMatrix, Matrix4x4& outputMatrix)
{
    Matrix4x4 tempMatrix;
 
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            //if (i == j) { continue; }
 
            tempMatrix.elements[i][j] = inputMatrix.elements[j][i];
        }
    }
 
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            //if (i == j) { continue; }
 
            outputMatrix.elements[i][j] = tempMatrix.elements[i][j];
        }
    }
}
 
 
void Math::CalculateCofactorMatrix(const Matrix4x4& inputMatrix, Matrix4x4& outputMatrix)
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            std::vector<int> horizontalIndexes = { 0, 1, 2, 3 };
            std::vector<int> verticalIndexes = { 0, 1, 2, 3 };
 
            std::vector<int>::iterator hPosition = std::find(horizontalIndexes.begin(), horizontalIndexes.end(), i);
            horizontalIndexes.erase(hPosition);
 
            std::vector<int>::iterator vPosition = std::find(verticalIndexes.begin(), verticalIndexes.end(), j);
            verticalIndexes.erase(vPosition);
 
            // Transpose matrix
            Matrix3x3 tempMatrix;
            for (int k = 0; k < 3; k++)
            {
                for (int l = 0; l < 3; l++)
                {
                    tempMatrix.elements[k][l] = inputMatrix.elements[horizontalIndexes[k]][verticalIndexes[l]];
                }
            }
 
            int sign = (i + j) % 2 ? -1 : 1;
 
            outputMatrix.elements[i][j] = CalculateDeterminant(tempMatrix) * sign;
        }
    }
}
 
 
void Math::DivideMatrixByScalar(const Matrix4x4& inputMatrix, Matrix4x4& outputMatrix, const float value)
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            outputMatrix.elements[i][j] = inputMatrix.elements[i][j] * value;
        }
    }
}
 
 
void Math::CalculateMatrixInverse(const Matrix4x4& inputMatrix, Matrix4x4& outputMatrix)
{
    // step 1: find the determinant
    float det = CalculateDeterminant(inputMatrix);
    Matrix4x4 tempMatrix;
 
    if (det == 0)
    {
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                tempMatrix.elements[i][j] = inputMatrix.elements[i][j];
            }
        }
 
        TransposeMatrix(tempMatrix, outputMatrix);
        return;
    }
 
    // step 2: calculate the matrix of cofactors
    CalculateCofactorMatrix(inputMatrix, tempMatrix);
 
    // step 3: transpose the matrix
    Matrix4x4 anotherTempMatrix;
    TransposeMatrix(tempMatrix, anotherTempMatrix);
 
    // step 4: divide matrix by determinant
    DivideMatrixByScalar(anotherTempMatrix, outputMatrix, 1 / det);
}
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
19.09.2016, 20:44  [ТС]     Объединение view и projection матриц #9
Тут скрин матриц (внизу).
Функция
C++
1
models[j].GetTransformedVertices()
возвращает уже трансформированные вертексы (потом изменю).
Проблема именно в цифре -8 (последняя матрица [2][2]). Из-за неё z и w компоненты "слетают" почему-то.
Миниатюры
Объединение view и projection матриц  
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
19.09.2016, 20:49  [ТС]     Объединение view и projection матриц #10
Тут скрин первого вертекса (два варианта), компонента z отличается из-за -15.0f, что во view матрице. А w кстати одна и та же. Мне казалось, что она тоже менялась.
Миниатюры
Объединение view и projection матриц  
Fulcrum_013
 Аватар для Fulcrum_013
497 / 613 / 68
Регистрация: 14.12.2014
Сообщений: 4,949
Завершенные тесты: 2
19.09.2016, 22:07     Объединение view и projection матриц #11
Такое впечатление что View транспанирована. Позиция обычно в нижней строке.

Добавлено через 26 минут
Кстати обычно подход к построению видовой матрицы абсолютно другой. Берут фрейм камеры, ось Z в качестве направления взгляда ось Y в качестве оси UP и строят LookAt матрицу. Т.е. фактически транспонируют подматрицу поворота (3x3) и вычисляют координаты ГСК в координатах фрейма, домножают на -1 и пишут в строку позиции.
Примерно вот так:
C++
1
2
3
4
5
6
7
8
9
10
        T3DUniformMatrix T3DUniformMatrix::GetViewMatrix(){
                T3DUniformMatrix R;
        R.AxeX.x = AxeX.x; R.AxeX.x = AxeY.x; R.AxeX.z = AxeZ.x; R.kx= 0;
        R.AxeY.x = AxeX.y; R.AxeY.y  = AxeY.y; R.AxeY.z = AxeZ.y; R.ky= 0;
        R.AxeZ.x = AxeX.z; R.AxeZ.z = AxeY.z; R.AxeZ.z = AxeZ.z; R.kz= 0;
    
            R.x = -(Eye*AxeX); R.y = -(Eye*Y);  R.z = -(Eye*Z); R.w = 1.0f;
        return R;
 
        }
Добавлено через 13 минут
Цитата Сообщение от Pro100Tom Посмотреть сообщение
что во view матрице
View матрица неправильно сформирована. эта -15 насколько понимаю должна быть в z. (т.е. в элементе [3][2]). Если конечно ползуешь Row Major матрицы. Если Column Major их надо перемножать в обратном порядке.
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
20.09.2016, 00:34  [ТС]     Объединение view и projection матриц #12
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Такое впечатление что View транспанирована
Тогда я запутался совсем. Почему? Вот тут описание translation матрицы. Изменения по оси x, y и z описаны справа. Значит и view матрица должна их справа описывать. Может у меня inverse не работает правильно, надо проверить. Буду гуглить еще раз view матрицу.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если конечно ползуешь Row Major матрицы
Первый индекс это ряд, второй - колонка.
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
20.09.2016, 01:10  [ТС]     Объединение view и projection матриц #13
Вот проектик. Разбил на четыре части, потому что больше десяти мб не разрешает загружать форум.
Вложения
Тип файла: rar 3D_Renderer_2016_August_09.part01.rar (10.00 Мб, 1 просмотров)
Тип файла: rar 3D_Renderer_2016_August_09.part02.rar (10.00 Мб, 1 просмотров)
Тип файла: rar 3D_Renderer_2016_August_09.part03.rar (10.00 Мб, 1 просмотров)
Тип файла: rar 3D_Renderer_2016_August_09.part04.rar (6.88 Мб, 1 просмотров)
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
20.09.2016, 01:15  [ТС]     Объединение view и projection матриц #14
Тут вот ещё в чём дело. Если я не перемножнаю на projection матрицу вообще, то всё работает. И если я изменяю z view матрицы, то объект либо "отдаляется" либо "приближается" в зависимости от значения. View матрица работает.
Fulcrum_013
 Аватар для Fulcrum_013
497 / 613 / 68
Регистрация: 14.12.2014
Сообщений: 4,949
Завершенные тесты: 2
20.09.2016, 17:40     Объединение view и projection матриц #15
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Изменения по оси x, y и z описаны справа.
Это в Column-major матрице так. В Row Major оси записаны в строках в нижней оси позиция. в правом столбце проекция. В Column-Major в первых трех столбцах оси в последнем столбце позиция в нижней колонке проекция.
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
20.09.2016, 18:49  [ТС]     Объединение view и projection матриц #16
У меня все матрицы значит в column major записаны.
scaling - не имеет значения, она симметрична.
rotation
cos() 0 sin() 0
0 0 0 0
-sin() 0 cos() 0
0 0 0 1

translation
1 0 0 Tx
0 1 0 Ty
0 1 0 Tz
0 0 0 1

view
1 0 0 0
0 1 0 0
0 0 1 -15
0 0 0 1

projection
s 0 0 0
0 s 0 0
0 0 a -1
0 0 b 0
где s = 1 / tan(0.5 * fov * pi / 180)
a = -f / (f - n)
b = -f * n / (f - n)

Добавлено через 46 минут
Скажите, правильно ли я понимаию стадии pipeline'а?
(пошагово для удобства)
1). TransformationMatrix - пропускаем оригинальные вертекса объекта, чтобы получить вертексы в World пространстве
2). ViewMatrix - пропускаем вертексы World пространства, чтобы получить вертексы в Camera пространстве
3). ProjectionMatrix - пропускаем вертексы Camera пространства через матрицу проекции, чтобы симулировать перспективу.
Для этого надо каждую компоненту каждого вертекса разделить на компоненту w.
После этого просто используем x и y, предварительно проверив находятся ли они в пределах окна.

Ничего не пропустил?
Fulcrum_013
 Аватар для Fulcrum_013
497 / 613 / 68
Регистрация: 14.12.2014
Сообщений: 4,949
Завершенные тесты: 2
20.09.2016, 20:12     Объединение view и projection матриц #17
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Скажите, правильно ли я понимаию стадии pipeline'а?
Ну примерно так. А если подробнее:
1) сборка примитивов. Т.е. Определение по индексам какие номера вертексов потребуются.
2) Трансформация. Т.е. умножение координат вертекса на матрицу трансформации. (произведение Model*View*Projection) (т.е. фактически то что делает VertexShader)
3) Отсечение. т.е. обрезка отрезков/треугольников/удаление точек вышедших за пределы пирамиды/куба перспективы (как минимум желательно обрезать плоскостью near)
4) Перспетивное деление.
5) Окончательное отсечение (обрезка остальными плоскостями если в пункте 3 резали только плоскостью near)
6) Масштабирование в ScreenSpace
7) Растеризация. т.е. вычисление закрашенных примитивами точек с учетом Z координаты (z интерполируется вдоль примитива) и сортировка по глубине (т.е. z-буфер). Для прошедших z-тест фрагментов вычисление освещенности (т.е. то что делает PixelShader)
Для отрисовки нурбсов и т.п. либо применяют более другие виды интерполяции нежели интерполяция плоскости треугольник при растеризации (в конвейерах профессиональных карт) либо добавляют еще одну стадию конвейера для разбиения патча на треугольники (в обычных домашних ускорителях то что делают Hull и Domain шейдеры) Стадия добавляется между 2 и 3.
Отсечение кстати задачка со многими неизвестными. Потому как по Near очень стоит отсекать до перспективного деления (при перспективном делении все что имеет отрицательный Z будет перевернуто вверх ногами что путает все карты при отсечении отрезков/треугольников вертексы которых лежат по разные стороны плоскости z=0, а вертексы имеющие z=0 вообще вылетят с ексекпшином или получат неопределенное значение). А с другой стороны удобнее отсекать после перспективного деления так как в результате перспективного деления пирамида отсечения превращается в куб отсечения.

Ну а вообще матрицы имеют свойство накапливать трансформацию. При этом в общем то не важно они Row Major или Column Major. Важен только порядок умножения.
К примеру для RowMajor нужно умножать Model*View*Projection и вектор координат умножать на матрицу. А для column Major умножать Projection*View*Model и матрицу умножать на вектор вертекса.

Добавлено через 10 минут
Цитата Сообщение от Pro100Tom Посмотреть сообщение
У меня все матрицы значит в column major записаны.
projection в RowMajor.
в Translation ошибка.
Должно быть
1 0 0 Tx
0 1 0 Ty
0 0 1 Tz
0 0 0 1
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
20.09.2016, 21:42  [ТС]     Объединение view и projection матриц #18
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
projection в RowMajor.
Спасибо, переведу сейчас. А по поводу translation - это опечатка.

Добавлено через 29 минут
Транспонировал я матрицу проекции - ни фига. Не работает!
Но вот, что забавно. И обычная и траспонированная матрица проекции визуализирует объект нормально. И fov работает как надо и eye (хоть он во view), единственное отличие, так это то, что в траспонированной матрице проекции объект перевёрнут.

Добавлено через 33 минуты
Нашёл!!!

Надо projection * view вместо view * projection!!!
Fulcrum_013
 Аватар для Fulcrum_013
497 / 613 / 68
Регистрация: 14.12.2014
Сообщений: 4,949
Завершенные тесты: 2
20.09.2016, 21:56     Объединение view и projection матриц #19
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Нашёл!!!
Надо projection * view вместо view * projection!!!
От перемены мест множителей результат транспанируется.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.09.2016, 22:03     Объединение view и projection матриц
Еще ссылки по теме:

Вычисление степени матрицы, вычисления произведения двух матриц, вычисление суммы двух матриц C++
C++ Что такое Model - View - Controller
C++ WinAPI Выбор tree-view control
C++ Model view controller
C++ WinAPI List View Control в WindowsXP

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 326
20.09.2016, 22:03  [ТС]     Объединение view и projection матриц #20
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
От перемены мест множителей результат транспанируется.
Сорри, не соглашусь с вами.
Yandex
Объявления
20.09.2016, 22:03     Объединение view и projection матриц
Ответ Создать тему
Опции темы

Текущее время: 12:34. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru