С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
 Аватар для Pro100Tom
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397

Компонента w вектора слишком большая

04.09.2014, 01:42. Показов 920. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здавствуйте. Пишу 3д рендеринг: без никаких opengl, directx и прочих api. В общем, как обычно, есть три матрицы: Transformation (состоит из Translation, Rotation, Scaling), View (сделал так, что она является центром пространства, сделал обычный transpose вместо inverse) и пытаюсь сделать Perspective Projection Matrix. Проблема заключается в том, что компонента W выходит намного больше чем компонеты x,y,z; Таким образом выходит что все эти значения приблизительно равны нулю. Получается непонятная белеберда. Пробовал различные матрицы perspective projection:http://www.codinglabs.net/arti... atrix.aspx
http://www.scratchapixel.com/l... on-matrix/
http://ogldev.atspace.co.uk/ww... ial12.html

Значения fieldOfView, near far, translate, scale, lookAt, eye менял по-всякому, всё равно ерунда какая-то.
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
void Matrix::BuildTransformationMatrix(bool rebuildAll)
{
    // translation matrix
    translationMatrix[0][0] = 1.0f;
    translationMatrix[1][0] = 0.0f;
    translationMatrix[2][0] = 0.0f;
    translationMatrix[3][0] = 0.0f;
 
    translationMatrix[0][1] = 0.0f;
    translationMatrix[1][1] = 1.0f;
    translationMatrix[2][1] = 0.0f;
    translationMatrix[3][1] = 0.0f;
 
    translationMatrix[0][2] = 0.0f;
    translationMatrix[1][2] = 0.0f;
    translationMatrix[2][2] = 1.0f;
    translationMatrix[3][2] = 0.0f;
 
    translationMatrix[0][3] = translateX;
    translationMatrix[1][3] = translateY;
    translationMatrix[2][3] = translateZ;
    translationMatrix[3][3] = 1.0f;
 
    // rotation matrix
    rotationMatrix[0][0] = cos(angle * pi / 180.0f);
    rotationMatrix[1][0] = 0.0f;
    rotationMatrix[2][0] = -sin(angle * pi / 180.0f);
    rotationMatrix[3][0] = 0.0f;
 
    rotationMatrix[0][1] = 0.0f;
    rotationMatrix[1][1] = -1.0f;
    rotationMatrix[2][1] = 0.0f;
    rotationMatrix[3][1] = 0.0f;
 
    rotationMatrix[0][2] = sin(angle * pi / 180.0f);
    rotationMatrix[1][2] = 0.0f;
    rotationMatrix[2][2] = cos(angle * pi / 180.0f);
    rotationMatrix[3][2] = 0.0f;
 
    rotationMatrix[0][3] = 0.0f;
    rotationMatrix[1][3] = 0.0f;
    rotationMatrix[2][3] = 0.0f;
    rotationMatrix[3][3] = 1.0f;
    
    // scaling matrix
    scalingMatrix[0][0] = scale;
    scalingMatrix[1][0] = 0.0f;
    scalingMatrix[2][0] = 0.0f;
    scalingMatrix[3][0] = 0.0f;
 
    scalingMatrix[0][1] = 0.0f;
    scalingMatrix[1][1] = scale;
    scalingMatrix[2][1] = 0.0f;
    scalingMatrix[3][1] = 0.0f;
 
    scalingMatrix[0][2] = 0.0f;
    scalingMatrix[1][2] = 0.0f;
    scalingMatrix[2][2] = scale;
    scalingMatrix[3][2] = 0.0f;
 
    scalingMatrix[0][3] = 0.0f;
    scalingMatrix[1][3] = 0.0f;
    scalingMatrix[2][3] = 0.0f;
    scalingMatrix[3][3] = 1.0f;
 
    float tempMatrix[4][4];
 
    // calculating temporary matrix
    Algorithms::MultiplyMatrices(translationMatrix, rotationMatrix, tempMatrix);
 
    // calculate transformation matrix
    Algorithms::MultiplyMatrices(tempMatrix, scalingMatrix, transformationMatrix);
 
    if(rebuildAll) BuildFinalMatrix();
    return;
}
 
void Matrix::BuildViewMatrix(bool rebuildAll)
{
    // firstly calculate view. View = normalise(at - eye)
    Vertex at = Vertex(0.0f, 0.0f, 1.0f, 1.0f);
    Vertex eye = Vertex(0.0f, 0.0f, 0.0f, 1.0f);
    Vertex view = at - eye;
    Algorithms::Normalise(view);
 
    // now we calculate right. Right = normalise(up X z)
    Vertex y = Vertex(0.0f, 1.0f, 0.0f, 1.0f);
    Vertex right = Algorithms::CrossProduct(y, view);
    Algorithms::Normalise(right);
 
    // finally we calculate up, Up = normalise(z X x)
    Vertex up = Algorithms::CrossProduct(view, right);
    Algorithms::Normalise(y);
 
    viewMatrix[0][0] = right.x;
    viewMatrix[1][0] = right.y;
    viewMatrix[2][0] = right.z;
    viewMatrix[3][0] = -eye.x;
 
    viewMatrix[0][1] = up.x;
    viewMatrix[1][1] = up.y;
    viewMatrix[2][1] = up.z;
    viewMatrix[3][1] = -eye.y;
 
    viewMatrix[0][2] = view.x;
    viewMatrix[1][2] = view.y;
    viewMatrix[2][2] = view.z;
    viewMatrix[3][2] = -eye.z;
 
    viewMatrix[0][3] = 0.0f;
    viewMatrix[1][3] = 0.0f;
    viewMatrix[2][3] = 0.0f;
    viewMatrix[3][3] = 1.0f;
 
    if (rebuildAll) BuildFinalMatrix();
    return;
}
 
void Matrix::BuildProjectionMatrix(bool rebuildAll)
{
    float fov = 90.0f;
    float s = 1 / (tan(fov * 0.5f * pi / 180));
    float nearPlane = -1.0f;
    float farPlane = 1.0f;
 
    projectionMatrix[0][0] = s;
    projectionMatrix[0][1] = 0.0f;
    projectionMatrix[0][2] = 0.0f;
    projectionMatrix[0][3] = 0.0f;
 
    projectionMatrix[1][0] = 0.0f;
    projectionMatrix[1][1] = s;
    projectionMatrix[1][2] = 0.0f;
    projectionMatrix[1][3] = 0.0f;
 
    projectionMatrix[2][0] = 0.0f;
    projectionMatrix[2][1] = 0.0f;
    projectionMatrix[2][2] = -((farPlane + nearPlane) / (farPlane - nearPlane));
    projectionMatrix[2][3] = -1.0f;
 
    projectionMatrix[3][0] = 0.0f;
    projectionMatrix[3][1] = 0.0f;
    projectionMatrix[3][2] = -(2.0f * farPlane * nearPlane / (farPlane - nearPlane));
    projectionMatrix[3][3] = 0.0f;
    
    if (rebuildAll) BuildFinalMatrix();
    return;
}
 
void Matrix::BuildFinalMatrix()
{
    float tempMatrix[4][4];
    Algorithms::MultiplyMatrices(projectionMatrix, viewMatrix, tempMatrix);
    Algorithms::MultiplyMatrices(tempMatrix, transformationMatrix, finalMatrix);
 
    //Algorithms::MultiplyMatrices(viewMatrix, transformationMatrix, finalMatrix);
}
Вот сам метод перемножения матриц
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Algorithms::MultiplyMatrices(float(&firstMatrix)[4][4], float(&secondMatrix)[4][4], float(&resultMatrix)[4][4])
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            resultMatrix[i][j] = firstMatrix[i][0] * secondMatrix[0][j] +
                firstMatrix[i][1] * secondMatrix[1][j] +
                firstMatrix[i][2] * secondMatrix[2][j] +
                firstMatrix[i][3] * secondMatrix[3][j];
        }
    }
 
    return;
}
Что я делаю нетак?

Добавлено через 5 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
float Matrix::translationMatrix[4][4];
float Matrix::rotationMatrix[4][4];
float Matrix::scalingMatrix[4][4];
float Matrix::transformationMatrix[4][4];
float Matrix::viewMatrix[4][4];
float Matrix::projectionMatrix[4][4];
float Matrix::finalMatrix[4][4];
 
float Matrix::angle = 90.0f;
float Matrix::translateX = 550.0f;
float Matrix::translateY = 350.0f;
float Matrix::translateZ = 1.0f;
float Matrix::scale = 70.0f;
 
const float Matrix::pi = 3.142f;
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.09.2014, 01:42
Ответы с готовыми решениями:

Константа слишком большая
В общем то вот, очень много таких ошибок, как исправить эту беду ??

Слишком большая нагрузка на ЦП
Дело в том,что после установки одной игры с торрента,у меня появился процесс Realtek который `жрал`40-60% цп и даже после его закрытия - он...

Слишком большая база
Я впервые создал базу данных в ACCES2000. Размер получился более 1,5 Мб. Другие готовые подобные базы в несколько раз меньше. Не пойму...

12
 Аватар для IrineK
2023 / 1641 / 425
Регистрация: 23.02.2011
Сообщений: 6,002
Записей в блоге: 25
04.09.2014, 01:45
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Вот сам метод перемножения матриц
Вложите ещё один цикл для подсчёта суммы.
0
 Аватар для Pro100Tom
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
04.09.2014, 01:47  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const Vertex operator * (const float matrix[4][4], const Vertex& vertex)
{
    return Vertex(matrix[0][0] * vertex.x +
        matrix[0][1] * vertex.y +
        matrix[0][2] * vertex.z +
        matrix[0][3] * vertex.w, 
 
        matrix[1][0] * vertex.x +
        matrix[1][1] * vertex.y +
        matrix[1][2] * vertex.z +
        matrix[1][3] * vertex.w,
 
        matrix[2][0] * vertex.x +
        matrix[2][1] * vertex.y +
        matrix[2][2] * vertex.z +
        matrix[2][3] * vertex.w,
        
        matrix[3][0] * vertex.x +
        matrix[3][1] * vertex.y +
        matrix[3][2] * vertex.z +
        matrix[3][3] * vertex.w);
}
Добавлено через 58 секунд
Цитата Сообщение от IrineK Посмотреть сообщение
Вложите ещё один цикл для подсчёта суммы.
Простите, не совсем понял вас.
0
 Аватар для IrineK
2023 / 1641 / 425
Регистрация: 23.02.2011
Сообщений: 6,002
Записей в блоге: 25
04.09.2014, 09:34
Цитата Сообщение от Pro100Tom Посмотреть сообщение
не совсем понял
Когда в коде возникают конструкции вида
r = a[0] + a[1] + a[2] + a[3]
очевидно, есть возможность изобразить это циклом.
Иначе, получается говнокод нехороший код
0
 Аватар для Pro100Tom
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
04.09.2014, 17:22  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Algorithms::MultiplyMatrices(float(&firstMatrix)[4][4], float(&secondMatrix)[4][4], float(&resultMatrix)[4][4])
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            resultMatrix[i][j] = 0.0f;
 
            for (int k = 0; k < 4; k++)
            {
                resultMatrix[i][j] += firstMatrix[i][k] * secondMatrix[k][j];
            }
        }
    }
 
    return;
}
Сделал. Теперь ваша очередь. Что не так с моим рендерингом. Если надо могу скинуть весь проект и файл, с которого читаю vertices и faces.
0
 Аватар для IrineK
2023 / 1641 / 425
Регистрация: 23.02.2011
Сообщений: 6,002
Записей в блоге: 25
04.09.2014, 17:39
Все матрицы тоже задаются циклами. Там есть явные закономерности.
Может быть, в процессе переосмысления и найдется баг.
0
 Аватар для Pro100Tom
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
04.09.2014, 20:07  [ТС]
Цитата Сообщение от IrineK Посмотреть сообщение
Все матрицы тоже задаются циклами.
Как же мне вот это задать циклом?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// translation matrix
    translationMatrix[0][0] = 1.0f;
    translationMatrix[1][0] = 0.0f;
    translationMatrix[2][0] = 0.0f;
    translationMatrix[3][0] = 0.0f;
 
    translationMatrix[0][1] = 0.0f;
    translationMatrix[1][1] = 1.0f;
    translationMatrix[2][1] = 0.0f;
    translationMatrix[3][1] = 0.0f;
 
    translationMatrix[0][2] = 0.0f;
    translationMatrix[1][2] = 0.0f;
    translationMatrix[2][2] = 1.0f;
    translationMatrix[3][2] = 0.0f;
 
    translationMatrix[0][3] = translateX;
    translationMatrix[1][3] = translateY;
    translationMatrix[2][3] = translateZ;
    translationMatrix[3][3] = 1.0f;
Не вижу ошибки. Без Projection Matrix, то есть если пропускать vertices через transformation и view matrices, то всё работает. Но хотелось бы матрицу перспективной проэкции. Можете сами посчтитать. Вот некоторые значения объекта:
Code
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
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 21.02.2013 21:53:29
 
#
# object default
#
 
v  -1.0552 1.8853 1.8378
v  -1.0110 2.5460 1.7188
v  -0.9699 3.1035 1.3935
v  -1.2661 3.0290 1.3896
v  -0.9381 3.4730 0.9117
v  -0.9197 3.4601 -0.2159
v  -1.3067 3.3626 -0.2211
v  -0.9359 3.0796 -0.6899
v  -1.2321 3.0050 -0.6939
v  -0.9666 2.5147 -1.0034
v  -1.0071 1.8514 -1.1086
v  -1.4094 2.2748 1.7154
v  -1.7060 2.6024 1.3873
v  -1.8999 2.8182 0.9035
v  -1.9615 2.8895 0.3377
v  -1.8815 2.8053 -0.2240
v  -1.6720 2.5784 -0.6961
v  -1.3650 2.2434 -1.0068
v  -1.9908 1.4262 1.3962
v  -1.9471 1.1130 1.4005
v  -2.2720 1.2815 0.9151
v  -2.2149 0.8723 0.9208
v  -2.3642 1.2261 0.3502
v  -2.3024 0.7832 0.3563
v  -2.2536 1.2685 -0.2124
v  -2.1965 0.8593 -0.2068
v  -1.9568 1.4022 -0.6873
v  -1.9131 1.0890 -0.6829
v  -1.4158 1.3458 1.7260
v  -1.7178 0.8858 1.4068
v  -1.9153 0.5755 0.9291
v  -1.9782 0.4619 0.3654
v  -1.8969 0.5625 -0.1985
v  -1.6838 0.8619 -0.6766
v  -1.3714 1.3145 -0.9962
v  -1.0957 1.2220 1.7326
v  -1.1264 0.6571 1.4191
v  -1.1426 0.2766 0.9451
v  -1.1418 0.1384 0.3827
v  -1.1242 0.2636 -0.1824
v  -1.0924 0.6331 -0.6643
v  -1.0513 1.1907 -0.9895
v  -1.5683 1.9789 1.7162
v  -1.9996 2.0556 1.3888
v  -2.2834 2.1038 0.9055
Возьмте любой vertex и попробуйте перемножить на матрицы. Wolfram Alpha вам в помощь. Компонента W получается очень большой.
0
 Аватар для IrineK
2023 / 1641 / 425
Регистрация: 23.02.2011
Сообщений: 6,002
Записей в блоге: 25
04.09.2014, 20:12
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Как же мне вот это задать циклом?
C++
1
2
3
4
5
6
7
8
9
10
for (int i = 0; i < 4; i++)
    for (int j = 0; j < 4; j++)
    translationMatrix[i][j] = 0.0f;
 
for (int i = 0; i < 4; i++)
    translationMatrix[i][i] = 1.0f;
 
translationMatrix[0][3] = translateX;
translationMatrix[1][3] = translateY;
translationMatrix[2][3] = translateZ;
0
 Аватар для Pro100Tom
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
04.09.2014, 20:24  [ТС]
Спасибо, но по-моему - это извращение. Если придётся изменить какое-нибудь значение, то придётся всю структуру цикла переделывать. Да и читабельность нарушается. Помогите мне не с точки зрения техники, а с точки зрения функциональности. Не работает матрица, не знаю, что еще пробовать.
0
 Аватар для IrineK
2023 / 1641 / 425
Регистрация: 23.02.2011
Сообщений: 6,002
Записей в блоге: 25
04.09.2014, 21:07
Цитата Сообщение от Pro100Tom Посмотреть сообщение
по-моему - это извращение
Согласна
1) создание матриц и заполнение нулями по дефолту логично вынести в отдельную функцию (лучше перейти к классам и доверить это конструктору)
2) translateX, translateY и translateZ - тоже вектор. Что вами не учитывается.

Цитата Сообщение от Pro100Tom Посмотреть сообщение
читабельность нарушается
Почти весело.

Нужны классы "Матрица", "Вектор".
Методы: сложение, умножение (матрица-матрица, матрица-вектор, матрица-число, вектор-число)

Цитата Сообщение от Pro100Tom Посмотреть сообщение
Пишу 3д рендеринг
Когда будут правильные инструменты, действия станут понятными и будут записываться в пару строк.
Без техники незачем это всё городить.
0
 Аватар для Pro100Tom
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
04.09.2014, 21:48  [ТС]
Цитата Сообщение от IrineK Посмотреть сообщение
Нужны классы "Матрица", "Вектор".
Насчёт вектора, то у меня есть класс Vertex. Считаю, что это более логично, так как вектор - это направленный отрезрок, а я работаю с точками и полигонами. Поправьте, если ошибаюсь. Насчёт матрицы, то у меня тоже есть Matrix класс, только там находятся всякие методы и так далее. Думал о том, чтобы создать матрицу как объект, но потом призадумался:
Code
1
Matrix matrix; matrix.something[0][0] = 1.0f
Подумал, ну нафиг такую ерунду, лучше напишу float matrix[4][4] и делов. Тем более, я могу через конструктор всю матрицу нулями заполнить. Не делал еще этого. А вот переписать операторы уже перемножения матриц я не могу. Приходится довольствоваться обычным методом.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Matrix::MultiplyMatrices(float(&firstMatrix)[4][4], float(&secondMatrix)[4][4], float(&resultMatrix)[4][4])
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            resultMatrix[i][j] = 0.0f;
 
            for (int k = 0; k < 4; k++)
            {
                resultMatrix[i][j] += firstMatrix[i][k] * secondMatrix[k][j];
            }
        }
    }
 
    return;
}
Добавлено через 3 минуты
Назревает вопрос: стоит ли ради наличия возможности и реализации оператора перемножения матриц создавать сам объект типа Matrix, у которого будет 16 полей или float[4][4]?
0
 Аватар для Pro100Tom
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
06.09.2014, 15:06  [ТС]
Решил сначала разобраться с ортогональной проекцией. Есть вопрос. На этом сайтеhttp://www.codinglabs.net/arti... atrix.aspx написано
To do the Orthographic projection we have to define the size of the area that the camera can see. This is usually defined with a width and height values for the x and y axis, and a near and far z values for the z axis (Figure 9).
И под ней картинка (вложил файл. называется ortho1.jpg). Потом написано вот это
Given these values we can create the transformation matrix that remaps the box area into the cuboid. The matrix that follows is transforms vectors from View Space into Ortho Projected Space and assumes a right handed coordinates system.
И под этим еще две картикни (orthoMatrix.jpg и ortho2.jpg). На картинке ortho2.jpg видно, что объект находится в кубу, границы которого являются {x,y,z} Э [-1, 1]. (Э - пусть будет "принадлежит промежутку"). Отсюда следует вывод, что все vertices чайника должны находиться в этом промежутке, так? Но у меня этого не происходит.
Заметил, что есть связь между значениями scale в transformation matrix и конечными значениями vertex'ов, после того, как пройдут через projection matrix. Не понимаю, ведь недолжно так быть. Model space - это model space. Он может быть каким угодно, ведь потом мы всё равно конвертируем всё в view space.
Может я ошибься с порядком перемножения? Поправьте меня, если я неправ. Сначала я создаю projection matrix, потом view. Перемножаю projection на view (не наоборот). Потом результат перемножаю на transformation matrix. После этого перемножаю матрицы на vertices.
Миниатюры
Компонента w вектора слишком большая   Компонента w вектора слишком большая  
Изображения
 
0
694 / 304 / 99
Регистрация: 04.07.2014
Сообщений: 851
08.09.2014, 16:58
1. Использовать массивы фиксированного размера как параметры и результат функции в С++ - очень плохая идея. С ними будут выскакивать различного рода проблемы (преобразование к double**, утечка памяти и т.д.). Лучше их обернут в структуры/классы, да и вообще в С++ удобнее использовать std::vector и std::array

2. У тебя каша с матрицами. "Повернуть относительно центра" и "сдвинуть" не тоже самое, что "сдвинуть" и "повернуть относительно центра". Поэтому у тебя должен быть класс "матрица", для которого определены статические функции для их генерации, определены операции умножения и т.д. Тогда ты сможешь более комфортно с ними работать. Например так:

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
#include <array>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <math.h>
 
class Matrix;
 
class Vertex {
public:
  Vertex(std::array<float,4> vector=std::array<float,4>()) : v(vector) {};
 
  std::string to_string() {
    std::stringstream ss;
    ss << std::setprecision(4) << std::fixed;
    for(int i=0; i<4; ++i)
      ss << std::setw(8) << v[i];
    return ss.str();
  };
 
  friend Vertex operator* (const Matrix &M, const Vertex &v);
private:
  std::array<float,4> v;
};
 
class Matrix {
public:
  Matrix(std::array<float,16> matrix=std::array<float,16>()) : A(matrix) {};
 
  static Matrix Translation(float dx, float dy, float dz) {
    return Matrix({ 1.0f, 0.0f, 0.0f,   dx ,
                    0.0f, 1.0f, 0.0f,   dy ,
                    0.0f, 0.0f, 1.0f,   dz ,
                    0.0f, 0.0f, 0.0f, 1.0f });
  };
 
  static Matrix RotateAroundXAxis(float phi) {
    return Matrix({ 1.0f,             0.0f,             0.0f, 0.0f ,
                    0.0f,  (float)cos(phi),  (float)sin(phi), 0.0f ,
                    0.0f, -(float)sin(phi),  (float)cos(phi), 0.0f ,
                    0.0f,             0.0f,             0.0f, 1.0f });
  };
  
  std::string to_string() {
    std::stringstream ss;
    ss << std::setprecision(4) << std::fixed;
    for(int i=0; i<16; ++i) {
      ss << std::setw(8) << A[i];
      if (i%4==3) ss << '\n';
    }
    return ss.str();
  };
 
  friend Vertex operator* (const Matrix &M, const Vertex &v);
  friend Matrix operator* (const Matrix &L, const Matrix &R);
private:
  std::array<float,16> A;
};
 
Matrix operator* (const Matrix &L, const Matrix &R) {
  Matrix M;
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      M.A[i*4+j] = L.A[i*4+0] * R.A[0*4+j] +
                   L.A[i*4+1] * R.A[1*4+j] +
                   L.A[i*4+2] * R.A[2*4+j] +
                   L.A[i*4+3] * R.A[3*4+j];
    };
  };
  return M;
};
 
Vertex operator* (const Matrix &M, const Vertex &v) {
  Vertex result;
  for (int i = 0; i < 4; i++) {
    result.v[i] = M.A[i*4+0] * v.v[0] +
                  M.A[i*4+1] * v.v[1] +
                  M.A[i*4+2] * v.v[2] +
                  M.A[i*4+3] * v.v[3];
  };
  return result;
};
 
int main() {
  Vertex v0({0.0f, 2.0f, 3.0f, 1.0f});
  std::cout << "v0: " << v0.to_string() << std::endl;
  Matrix m1 = Matrix::Translation(0.0f, 1.0f, 1.0f) * Matrix::RotateAroundXAxis(1.0f);
  std::cout << "m1:\n" << m1.to_string() << std::endl;
  Vertex v1 = m1*v0;
  std::cout << "v1: " << v1.to_string() << std::endl;
  Matrix m2 = Matrix::RotateAroundXAxis(1.0f) * Matrix::Translation(0.0f, 1.0f, 1.0f);
  std::cout << "m2:\n" << m2.to_string() << std::endl;
  Vertex v2 = m2*v0;
  std::cout << "v2: " << v2.to_string() << std::endl;
  return 0;
};
Добавлено через 12 минут
К порядку умножения. Тут надо помнить, что умножение матриц (вектор - это тоже матрица) ассоциативно, но не коммутативно. Если ты хочешь передвинуть (T) вектор (v0), а потом его повернуть (R), то справедливо следующее:

v1 = T*v0; v2 = R*v2;
v2 = R*(T*v0)
v2= (R*T)*v0
M=R*T; v2=M*v0
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.09.2014, 16:58
Помогаю со студенческими работами здесь

Константа слишком большая
masm model small .stack 1000h .data x dw 0 y dw 0 z dw 0 F dw ?

Слишком большая громкость в наушниках
Здравствуйте, уважаемые форумчане! Возникла такая проблема: была проблема со звуком, когда пользовались наушником, включённым прямо в...

Слишком большая длина записи
Добрый день. Не нашла ничего конкретного по этой теме. Есть проблема: выгружая определенную запись со всеми атрибутами из...

Слишком большая длина записи
Добрый день, При попытке добавить новые поля в действующую базу, выдает ошибку &quot;Слишком большая длина записи&quot; и не позволяет...

Слишком большая громкость в наушниках
Доброго времени суток! Уже давно не могу решить проблему с наушниками. Наблюдается только в операционной системе Windows. Дело в...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru