DirectX 8 - Урок 2. Использование матриц преобразований
Что такое матрицы преобразований и зачем они нужны ? Перед тем как разобраться с этим понятием, вспомним немного математику.
Пусть у нас имеется некая вершина v1 , которую мы хотим переместить в вершину v2, вращая ее против часовой стрелки на угол A.
Рисунок 1. Поворот вершины против часовой стрелки
Воспользовавшись простыми формулами, находим координаты точки v2:
x2 = x1*cos(A) y2 = y1*sin(A) , где x1 и y1 - координаты точки v1
Зная правило умножения вектора на матрицу, мы можем записать наши формулы в более элегантном виде:
| x | | a11 a12 | = | x' | | y | | a21 a22 | | y' |
, где x' = x*a11 + y*a21 y' = x*a12 + y*a22
подставив a11 = cos(A), a12 = 0, a21 = 0, a22 = sin(A), получим:
| x2 | = | x1 | | cos(A) 0 | | y2 | | y1 | | 0 sin(A) |
, где x2 = x1*cos(A) y2 = y1*sin(A)
тем самым, мы получили некую матрицу M, которая и является матрицей преобразования, предназначенная для вращения любой вершины на произвольный угол.
M = | cos(A) 0 | | 0 sin(A) |
Когда вы работаете с 3-D графикой, вы можете преобразовывать любую вершину в другую, используя уже 4-х мерную матрицу.
Основные матричные преобразования - это перемещение, вращение и масштабирование. Следующая матрица перемещает вершину (x,y,z) в вершину (x',y',z') на расстояние Tx, Ty, Tz:
Для вращение вершины (x,y,z) вокруг произвольной координатной оси, используются следующие матрицы:
,вращение вокруг оси X
,вращение вокруг оси Y
,вращение вокруг оси Z
Для масштабирования вершины (x,y,z) на коэффициенты Sx,Sy,Sz, применяется следующая матрица:
Несмотря на кажущийся громоздкость применения матриц, у них есть одно
неоспоримое преимущество. Чтобы получить несколько преобразований сразу, не
нужно каждый раз умножать вершину на новую матрицу, достаточно лишь
предварительно перемножить все матрицы и получить одну результирующею матрицу:
W = M1*M2*M3
,где например M1 - матрица поворота вокруг оси X, M2 - матрица перемещения, M3 -
матрица масштабирования. Тогда умножая любую вершину на матрицу W , мы получим три преобразования сразу.
Понятие матриц неразрывно связано с понятием геометрического конвейера Direct3D. Он состоит из трех матриц преобразования:
Рисунок 2. Геометрический конвейер Direct3D
Входными данными геометрического конвейера являются вершины, точнее их
координаты ( Vertices - вершины ). Они последовательно преобразуются через три
матрицы: World - мировую, View - видовую, Projection - проекционную. Потом все точки проходят отсечение - clipping ( т.е. отсекаются все точки, которые не будут
видны на экране ), масштабируются и приводятся к экранным координатам - viewport scalling .
Рассмотрим все три преобразования:
1. Мировое преобразование меняет локальные координаты модели, в мировые координаты.
2. Видовое преобразование, отражая расположение наблюдателя в мировом пространстве, преобразует точки в пространство камеры.
3. Проективное преобразование переносит координаты точек из пирамиды просмотра
(viewing frustum) в кубоид, который потом и будет отражаться на экране.
Теперь плавно перейдем от теоретической части к практической. Возьмем за
основу пример из первого нашего урока. Сперва напишем функцию, которая будет
устанавливать матрицы преобразования геометрического конвейера Direct3D:
void SetMatrices(void)
{
D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DXMATRIX matProj;
D3DXMatrixRotationY(&matWorld,timeGetTime()/f);
d3d_device->SetTransform(D3DTS_WORLD,&matWorld);
D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(f,f,-f),
&D3DXVECTOR3(f,f,f),
&D3DXVECTOR3(f,f,f));
d3d_device->SetTransform(D3DTS_VIEW,&matView);
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,f,f,f);
d3d_device->SetTransform(D3DTS_PROJECTION,&matProj);
} |
Немного изменим функцию прорисовки сцены, добавив в нее вызов предыдущей функции:
void RenderDirect3D(void)
{
d3d_device->Clear(0,NULL,D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,0,0),f,0);
d3d_device->BeginScene();
SetMatrices();
d3d_device->SetStreamSource(0,d3d_vb,sizeof(CUSTOMVERTEX));
d3d_device->SetVertexShader(D3DFVF_CUSTOMVERTEX);
d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST,0,3);
d3d_device->EndScene();
d3d_device->Present(NULL,NULL,NULL,NULL);
} |
Вот и все, мы получим два вращающихся объекта, которые раньше у нас были просто
плоскими. Полный исходный текст программы и exe-файл можно взять
здесь.
Взято с DirectX Design
|