Матрица вида в directx

Обновлено: 04.07.2024

Если открыть пример - появится 2 окна с чайниками. Поверните чайник таким образом, чтобы он его носик был направлен в экран (потяните мышью справа налево). Далее потяните мышью сверху вниз. Лично я ожидаю, что в этом случае носик должен уйти вниз, а ручка чайника должна стать видимой, но этого не происходит, чайник вращается в другой плоскости.

Кто-нибудь может подсказать как бороться с данной проблемой?
Спасибо за советы.

Делать самому D3DXMatrixRotationY*D3DXMatrixRotationX*D3DXMatrixRotationZ или другой комбинацией

Так как поворот на углы в матрицах это очень неопределенно. Тоесть сначала повернуть по X а потом на Y - это нетоже самое, что сначала на Y, а потом на X. Ну и Z соответственно.

Che@ter
Это к чему??
D3DXMatrixRotationYawPitchRoll
работает даже очень замечательно.
думаю тут больше проблема в понимании преобразований в 3Д пространстве чем в построении самих преобразований.

Mightimus
Ну к тому, что D3DXMatrixRotationYawPitchRoll реально может показать неожиданные результаты. X*Y*Z != X*Z*Y!=Y*Z*X и так далее.. конечно коечто может совпасть, но єто к тому, что и не может. Мне D3DXMatrixRotationYawPitchRoll тоже не подошел. Делал не то, что ожидалось. Особенно если управление через мышку.

Я как раз тоже работаю над управлением через мышь. Еще нашел пример на OpenGL, в котором, как я понял, инвертируется матрица вида, таким образом достигается как бы смена осей. Может и в DirectX можно сделать что-нибудь подобное?

Che@ter
>>X*Y*Z != X*Z*Y!=Y*Z*X
Ты о чём ?? :)
Построение преобразования в углах Эйлера, это заранее пред определённый сиквенс операций и я ни как не могу уловить смысл этого выражения.

Mightimus
X - матрица поворота по X
Y - матрица поворота по Y
Z - матрица поворота по Z

D3DXMatrixRotationYawPitchRoll = Y*X*Z
+ попробуй сам построить матрицы поворотов и поумножать разными комбинациями. Получишь гдето 3 разных варианта(если не больше).

Кстати вот, что говорят доки:
The order of transformations is roll first, then pitch, then yaw. Relative to the object's local coordinate axis, this is equivalent to rotation around the z-axis, followed by rotation around the x-axis, followed by rotation around the y-axis.
..так как порядок умножения важен.

Еще раз всем привет. Я прочитал в одной статье, что такие проблемы в DirectX решаются при помощи кватернионов. Никогда с ними не работал. В SDK полно информации о том, как умножить один кватернион на другой и как получить необходимые преобразования, но нет информации о том, как заставить IDirect3DDevice9 его использовать. Кто-нибудь знает есть ли что-то аналогичное IDirect3DDevice::SetTransform() для кватернионов?

Che@ter
Ты опять о чём?? может я тебя плохо понимаю.
Погугли. Та функция, это представление частного случая вращения с помощью использования углов Эйлера.
Я не понимаю что тебе в ней не нравится, или почему она работает не правильно (. ).

Mightimus
Понимаешь, в матрицах A*B!=B*A (чаще всего). D3DXMatrixRotationYawPitchRoll() = D3DXMatrixRotationY*D3DXMatrixRotationX*D3DXMatrixRotationZ.
Походу для движения мышкой нужно
D3DXMatrixRotationX*D3DXMatrixRotationZ*D3DXMatrixRotationY. А ЭТО УЖЕ НЕ D3DXMatrixRotationYawPitchRoll !! Но тоже поворачивает на заданные углы!

Для того, чтобы вращать объекты (или камеру), необходима серьезная математическая база, с помощью которой будут расчитываться координаты всех объектов при выводе на "плоский" экран компьютера. Сразу хочу сказать, что не стоит пугаться, все математические библиотеки уже написаны за нас, мы будем их только использовать. В любом случае, следующий текст пропускать не нужно, независимо от уровня знаний математики.

1. Матрицы, общие понятия

Что такое матрицы? Вспоминаем высшую математику: матрица ¬- это набор чисел с заранее известной размерностью строк и столбцов.

Наша задача - создать объект, т.е. заполнить матрицу координатами вершин объекта. Каждая вершина - это вектор (X, Y, Z) в трехмерном пространстве. Теперь, чтобы произвести какое-то действие, нужно взять наш объект (то есть матрицу) и умножить на матрицу преобразования, результат этой операции - новый объект, заданный в виде матрицы.

В Direct3D определены и используются три основные матрицы: мировая матрица, матрица вида и матрица проекции. Рассмотрим их подробнее.

Мировая матрица (World Matrix) - позволяет производить вращение, трансформацию и масштабирование объекта, а также наделяет каждый из объектов своей локальной системой координат.

Функции для работы с мировой матрицей:

Матрица вида (View Matrix) - определяет местоположение камеры просмотра сцены и может состоять из любых комбинаций трансляции и вращения.
D3DXMatrixLookAtLH()и D3DXMatrixLookAtRH() определяет положение камеры и угла просмотра для левостороней и правостороней систем координат соответственно.

Матрица проекции (Projection Matrix) - создает проекцию 3D сцены на экран монитора. С ее помощью объект трансформируется, начало координат переносится в переднюю часть, а также определяется передняя и задняя плоскости отсечения.

Заполняя эти матрицы и делая преобразования, вы создаете трехмерную сцену, в которой получаете возможность перемещать, вращать, приближать, удалять и производить другие действия над объектами, в зависимости от ваших потребностей.

2. Создание объекта

Добавляем заголовочный файл и библиотеку для использования матричных функций

Также нам понадобятся стандартные функции работы со временем, поэтому подключаем соответствующий заголовочный файл:

Изменим формат представления вершин:

Будем использовать не преобразованный тип вершин, т.к. преобразования будем делать матрицами.
Изменяем код функции InitDirectX(). В эту функцию необходимо добавить установку двух режимов отображения.
Отключаем режим отсечения для того, чтобы при вращении можно было видеть все стороны объекта:

На данный момент мы не пользуемся освещением, а закрашиваем вершины в определенный цвет, поэтому отключаем освещение:

Упростим наше сердце, представив его в виде трех треугольников. Будем использовать локальную систему координат.

Программирование с использованием DirectX9

3. Создание матриц преобразования

Напишем в файле render.h функцию SetupMatrix() в которой будут происходить все действия над матрицами.

Для того, чтобы объект вращался, необходимо получить системное время и каждое "мгновение" изменять угол между локальной системой координат и мировой ситемой координат. Вращать будем относительно оси Х, поэтому используем функцию D3DXMatrixRotationX. После расчета мировой матрицы необходимо применить ее значения с помощью функции SetTransform:

Установка матрицы вида

Устанавливаем камеру в нужном месте и направляем ее на объект

После расчета необходимо применить полученные значения:

Установка матрицы проекции

После просчета необходимо применить полученные значения:

Помещаем вызов функции расчета матриц в функцию отрисовки сцены RenderScene().
Запускаем на компиляцию и наблюдаем вращение :)

В компьютерной графике определенны понятия различных матриц. Это мировая матрица (World Matrix), матрица вида (View Matrix) и матрица проекции (Projection Matrix). С помощью данных матриц в исходном коде программы производятся матричные преобразования над моделями. Матричные преобразования подразумевают под собой умножение каждой вершины объекта на одну из матриц, а точнее последовательное умножение всех вершин объекта на каждую из трех матриц. Такой подход позволяет корректно представить модель в трехмерном пространстве вашего двухмерного монитора. Техника прохода модели через три перечисленные матрицы представляет суть механизма работы с графическими данными в трехмерной плоскости монитора.

Мировая матрица

Мировая матрица – позволяет производить различные матричные преобразования (трансформацию и масштабирование) объекта в мировой системе координат. Мировая система координат – это своя локальная система координат данного объекта, которой наделяется каждый объект, скажем так прошедший через мировую матрицу, поскольку каждая вершина участвует в произведении этой матрицы.

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

Как уже упоминалось, мировое преобразование вершин объекта может состоять из любых комбинаций вращения, трансляции и масштабирования. В математической записи вращение вершины по оси Х выглядит следующим образом:


Мировая матрица

где cos — угол вращения в радианах.

Вращение вершины вокруг оси Y выглядит так:


Вращение вершины вокруг оси Y

А вращение вокруг оси Z происходит по следующей формуле:


вращение вокруг оси Z

Трансляция вершины позволяет переместить эту саму вершину с координатами x, y, z в новую точку с новыми координатами x1, y1, z1. В математической записи это выглядит так:

Трансляция вершины в матричной записи выглядит следующим образом:


Трансляция вершины в матричной записи

где Tx, Ty и Tz — значения смещения по осям X, Y и Z.

Масштабировать вершину в пространстве (удалять или приближать) с координатами x, y, z в новую точку с новыми значениями x1, y1, z1, можно посредством следующей записи:

В матричной записи это выражается следующим образом:


Масштабировать вершину

где Sx, Sy, Sz — значения коэффициентов растяжения или сжатия по осям X, Y, Z.

Все перечисленные операции можно делать в исходном коде программы вручную, то есть вычислять приведенные записи так, как я их только что описал. Но естественно так никто не делает (почти никто), потому что в DirectX имеется огромное количество методов, которые сделают все выше приведенные операции за вас.

Матрица вида

Матрица вида – задает местоположение камеры в пространстве и это вторая по счету матрица, на которую умножаются вершины объекта. Эта матрица способствует определению направления просмотра трехмерной сцены. Трехмерная сцена – это все то, что вы видите на экране монитора. Это как в театре, где вы сидите в портере или на галерке и наблюдаете за действиями на сцене. Так вот сидя в портере у вас будет одно местоположение камеры, а сидя на галерке уже совсем другое.

Фактически эта матрица позволяет определять жанр игры. Например, игра DOOM от первого лица – это можно сказать первые ряды портера в театре, тогда как игра Warcraft – это галерка на балконе. Матрица вида предназначена для определения положения камеры в пространстве, и вы можете смещать позицию камеры влево, вправо, вверх, вниз, удалять, приближать ее и так далее.

Матрица проекции

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


Матрица проекции

Преобразование «проекция» можно рассматривать как управление внутренними функциями камеры. аналогично выбору линзы для камеры. Это самый сложный из всех трех типов преобразований. Это обсуждение преобразования «проекция» организовано в следующие разделы.

Обычно матрица проекции — это проекция масштаба и перспективы. Проекционное преобразование превращает видимое пространство (усеченную пирамиду) в кубовидную фигуру. Так как ближний конец видимого пространства меньше дальнего, это приводит к развертыванию объектов, которые находятся ближе к камере — так перспектива применяется к сцене.

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

иллюстрация матрицы проекции

Матрица просмотра переносит камеру в начало координат, перемещаясь в направлении z на –D. Матрицы преобразования выглядит, как показано на следующем рисунке.

иллюстрация матрицы преобразования

Умножение матрицы преобразования на матрицу проекции (T * P) дает матрицу составной проекции, как показано на следующем рисунке.

иллюстрация составной матрицы проекции

Преобразование перспективы превращает видимое пространство в новое пространство координат. Обратите внимание, что усеченная пирамида становится кубоидом, а начало координат перемещается из правого верхнего угла сцены в центр, как показано на следующем рисунке.

схема изменения усеченной пирамиды обзора в новое пространства координат за счет преобразования перспективы

При преобразовании перспективы ограничения направлений x и y равны –1 и 1 соответственно. Ограничения по оси z равны 0 для передней плоскости и 1 для задней плоскости.

Эта матрица преобразует и масштабирует объекты на основе определенного расстояния между камерой и ближней плоскостью отсечения, но при этом не учитывается, что поле зрения (fov) и z-значения, создаваемые для объектов, на расстоянии могут быть практически идентичными, что усложняет сравнение глубины. Следующая матрица решает эти проблемы и корректирует вершины для учета пропорций окна просмотра, что хорошо подходит для проекции перспективы.

иллюстрация матрицы для проекции перспективы

В этой матрице Zₙ — это z-значение ближней плоскости отсечения. Переменные w, h и Q имеют следующие значения. Обратите внимание, что fovw и fovₖ представляют горизонтальные и вертикальные поля зрения окна просмотра в радианах.

формулы значений переменных

В вашем приложении использование углов полей зрения для определения коэффициентов масштабирования осей x и y может быть не так удобно, как применение горизонтального и вертикального измерения окна просмотра (в пространстве камеры). В следующих двух уравнениях для w и h используются измерения окна просмотра, при этом они эквивалентны предыдущим формулам.

формулы значений переменных w и h

В этих формулах Zₙ представляет положение ближней плоскости отсечения, а переменные Vw и Vₕ представляют ширину и высоту окна просмотра в пространстве камеры.

Для приложения C++ эти два измерения непосредственно соответствуют элементам Width и Height структуры D3DVIEWPORT9 .

Какую бы формулу вы ни выбрали, обязательно установите для Zₙ максимально возможное значение, так как z-значения, очень близкие к камере, не сильно отличаются. Это относительно усложняет сравнение глубины с помощью 16-разрядных z-буферов.

Как и в случае с преобразованиями мира и представлений, вы вызываете метод IDirect3DDevice9:: сеттрансформ , чтобы задать преобразование проекции.

Настройка матрицы проекции

В приведенной ниже образце функции Прожектионматрикс задаются фронтальные и обратные плоскости, а также горизонтальное и вертикальное поле углов представления. Поля представления должны быть меньше PI радиан.

После создания матрицы задайте IDirect3DDevice9:: сеттрансформ , указав D3DTS _ проекцию.

Библиотека служебной программы D3DX предоставляет следующие функции, помогающие настроить матрицу проекции.

Матрица проекций с поддержкой W

Direct3D может использовать компонент w вершины, которая была преобразована абсолютной матрицей, а также матрицами представления и проекции для вычислений на основе глубины при использовании буфера глубины или эффекта тумана. Для таких вычислений требуется, чтобы матрица проекции нормализовала переменную w как эквивалентную координате z в абсолютном пространстве. Иными словами, если матрица проекции включает коэффициент (3,4), не равный 1, необходимо масштабировать все коэффициенты, инвертируя коэффициент (3,4) для получения правильной матрицы. Если не предоставить совместимую матрицу, эффекты тумана и буферизация глубины не будут правильно применены.

На следующем рисунке показана несоответствующая требованиям матрица проекции и та же матрица, масштабированная для применения тумана туман относительно зрителя.

иллюстрации несоответствующей матрицы проекции и матрицы с туманом относительно зрителя

В предыдущих матрицах предполагается, что все переменные не равны нулю. Дополнительные сведения о относительном тумане с учетом взгляда см. в разделе глубина, относительная относительно глаз и Z. Сведения о буферизации глубины на основе w см. в разделе буферы глубины (Direct3D 9).

Direct3D использует текущую матрицу проекции при расчетах глубины вершин на основе переменной w. В результате приложения должны установить соответствующую матрицу проекции для получения необходимых функций на основе компонента w, даже если они не используют Direct3D для преобразования.

Читайте также: