Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
1

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

19.09.2016, 11:45. Показов 2147. Ответов 28
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте!

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

Если издалека, то чтобы обработать вертексы, мы их пропускаем через 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 совсем другая становится.

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

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

Заранее спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.09.2016, 11:45
Ответы с готовыми решениями:

Объединение View из разных баз
Есть 3 базы в них одинаковые поля и одинаковые view по этим полям, нужно чтобы данные шли в 4 базу...

Объединение матриц
как можно объединить 2 матрицы типа char? чтобы результат второй записывался с права как на...

Объединение вложенных матриц
Здравствуйте) не могу объединить вложенные матрицы дело в том что количество их неизвестно ...

Объединение матриц в MathCad
Добрый день или вечер, у меня возник такой вопрос имеется вектор размерности 3 каждый элемент...

28
Модератор
2904 / 1763 / 179
Регистрация: 19.02.2011
Сообщений: 6,477
19.09.2016, 17:43 2
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Я пока код решил не скидывать
Код на чем пишется?
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
19.09.2016, 18:23  [ТС] 3
Цитата Сообщение от TanaTiX Посмотреть сообщение
Код на чем пишется?
С++
Скинуть?
0
Модератор
2904 / 1763 / 179
Регистрация: 19.02.2011
Сообщений: 6,477
19.09.2016, 18:52 4
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Скинуть?
Нет, туда сейчас тема переедет. В 3D-моделировании ей явно не место. Хотя наверняка там попросят код, так что скинуть лишним не будет.
1
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
19.09.2016, 19:14 5
Цитата Сообщение от Pro100Tom Посмотреть сообщение
А если я сначала перемножаю эти две матрицы и перемножаю вертексы на viewProjection матрицу, то получается... да вообще ничего не получается. Там компонента z и w совсем другая становится.
Если сами матрицы построены правильно и правильно работает перемножение то все там получается. Причем произведение всех трех сразу Model*View*Projection. Именно в таком порядке. При этом обычно еще хранят произведение View*Projection потому как оно меняется обычно раз в кадр а Model меняется на каждый объект, поэтому перемножают Model * ViewProjection для экономии матричных умножений при переходе от объекта к объекту.

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

Добавлено через 1 минуту
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если сами матрицы построены правильно и правильно работает перемножение то все там получается.
Спасибо! Буду искать ошибку. Как вернусь с работы, скину весь проект и ключевые функции. Если кто сможет помочь найти ошибку, буду очень признателен.
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
19.09.2016, 19:23 7
Цитата Сообщение от Pro100Tom Посмотреть сообщение
CPU rendering, никаких дополнительных либ, всё ручками сделал, вплоть до алгоритма рисования и закрашивания треугольников
Стоит поискать ошибку в умножении и формировании матриц.
У меня для того чтобы ошибок не было код операций между матрицами и векторами машинно-генерированный
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Если кто сможет помочь найти ошибку, буду очень признателен.
Скинь код построения матриц проекции и вида
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
19.09.2016, 20:38  [ТС] 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);
}
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
19.09.2016, 20:44  [ТС] 9
Тут скрин матриц (внизу).
Функция
C++
1
models[j].GetTransformedVertices()
возвращает уже трансформированные вертексы (потом изменю).
Проблема именно в цифре -8 (последняя матрица [2][2]). Из-за неё z и w компоненты "слетают" почему-то.
Миниатюры
Объединение view и projection матриц  
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
19.09.2016, 20:49  [ТС] 10
Тут скрин первого вертекса (два варианта), компонента z отличается из-за -15.0f, что во view матрице. А w кстати одна и та же. Мне казалось, что она тоже менялась.
Миниатюры
Объединение view и projection матриц  
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
19.09.2016, 22:07 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 их надо перемножать в обратном порядке.
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
20.09.2016, 00:34  [ТС] 12
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Такое впечатление что View транспанирована
Тогда я запутался совсем. Почему? Вот тут описание translation матрицы. Изменения по оси x, y и z описаны справа. Значит и view матрица должна их справа описывать. Может у меня inverse не работает правильно, надо проверить. Буду гуглить еще раз view матрицу.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если конечно ползуешь Row Major матрицы
Первый индекс это ряд, второй - колонка.
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
20.09.2016, 01:10  [ТС] 13
Вот проектик. Разбил на четыре части, потому что больше десяти мб не разрешает загружать форум.
Вложения
Тип файла: rar 3D_Renderer_2016_August_09.part01.rar (10.00 Мб, 2 просмотров)
Тип файла: rar 3D_Renderer_2016_August_09.part02.rar (10.00 Мб, 2 просмотров)
Тип файла: rar 3D_Renderer_2016_August_09.part03.rar (10.00 Мб, 2 просмотров)
Тип файла: rar 3D_Renderer_2016_August_09.part04.rar (6.88 Мб, 2 просмотров)
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
20.09.2016, 01:15  [ТС] 14
Тут вот ещё в чём дело. Если я не перемножнаю на projection матрицу вообще, то всё работает. И если я изменяю z view матрицы, то объект либо "отдаляется" либо "приближается" в зависимости от значения. View матрица работает.
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
20.09.2016, 17:40 15
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Изменения по оси x, y и z описаны справа.
Это в Column-major матрице так. В Row Major оси записаны в строках в нижней оси позиция. в правом столбце проекция. В Column-Major в первых трех столбцах оси в последнем столбце позиция в нижней колонке проекция.
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
20.09.2016, 18:49  [ТС] 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, предварительно проверив находятся ли они в пределах окна.

Ничего не пропустил?
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
20.09.2016, 20:12 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
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
20.09.2016, 21:42  [ТС] 18
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
projection в RowMajor.
Спасибо, переведу сейчас. А по поводу translation - это опечатка.

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

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

Надо projection * view вместо view * projection!!!
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
20.09.2016, 21:56 19
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Нашёл!!!
Надо projection * view вместо view * projection!!!
От перемены мест множителей результат транспанируется.
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
20.09.2016, 22:03  [ТС] 20
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
От перемены мест множителей результат транспанируется.
Сорри, не соглашусь с вами.
0
20.09.2016, 22:03
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.09.2016, 22:03
Помогаю со студенческими работами здесь

Объединение матриц по условию
Добрый день! Помогите, пожалуйста) Сделал генератор псевдослучайной последовательности...

Объединение трёх матриц в цикле
Имеется три матрицы x,y,z X = X11 X12 X13 X21 X22 X23 X31 X32 X33 ...

Объединение нескольких матриц в одну
Здравствуйте. Имеется 4096 матриц порядка 8х8. Необходимо объединить их в одну квадратную матрицу...

Hibernate projection for nested entity
Добрый день! Возникла такая проблемка. У меня есть две таблицы с кучей полей, связаны...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru