Создание игр » Featured, Теория » Навигация в трёхмерном пространстве
Навигация в трёхмерном пространстве
Навигация в трёхмерном пространстве часто представляет собой проблему для начинающих программистов. Особенно, для тех, кто не до конца понимает как работают матрицы, либо просто не догадывается, что они содержат в себе практически готовое решение их проблемы. Часто для навигации в 3D программисты берут единичные вектора и, путём умножения их на матрицу вида камеры, получают вектора для навигации. Однако, если немного разобраться в проблеме и попытаться математически прикинуть решение задачи, оказывается, что даже эти вычисления совершенно лишние и что вектора для навигации уже содержатся в используемых матрицах и надо лишь знать, откуда их извлечь, и не более того.
В предыдущих уроках по матрицам (см. Урок “Матрицы”) я уже объяснял, что любая матрица трансформации есть ни что иное, как три вектора-базиса. Каждый из этих векторов является вектором, задающим ось координат “нового пространства” в “старом пространстве”. При этом, как обычно, один из этих векторов направлен (в новом пространстве) вбок, один вверх(либо вниз), а третий либо к “камере”, либо от неё.
Для навигации в трёхмерном пространстве, обычно так же необходимо иметь всего три вектора – один вбок (для стрейфа), один к камере либо от неё (что бы ходить вперёд/назад) и один вверх, либо вниз (для прыжков, например). Наблюдаете сходство с тем, что я написал в предыдущем абзаце? Проверим на практике, как оно работает?
Получение векторов для навигации в 3D
Итак, надеюсь, вы понимаете, что необходимые нам для навигации вектора мы можем извлечь непосредственно из матрицы трансформации объекта. Возможно, это стоило бы сделать для камеры, но, мне кажется, что в будущем нам понадобятся такие вектора и для других объектов, потому я реализовал эти методы в классе CEntity:
D3DXVECTOR3 GetUp() const; D3DXVECTOR3 GetRight() const; D3DXVECTOR3 GetForward() const; |
Вот как выглядит их исходный код:
D3DXVECTOR3 CEntity::GetUp() const { D3DXVECTOR3 v(m_matrix._21, m_matrix._22, m_matrix._23); D3DXVec3TransformCoord(&v, &v, &GetParentMatrix()); return v; } D3DXVECTOR3 CEntity::GetRight() const { D3DXVECTOR3 v(m_matrix._11, m_matrix._12, m_matrix._13); D3DXVec3TransformCoord(&v, &v, &GetParentMatrix()); return v; } D3DXVECTOR3 CEntity::GetForward() const { D3DXVECTOR3 v(m_matrix._31, m_matrix._32, m_matrix._33); D3DXVec3TransformCoord(&v, &v, &GetParentMatrix()); return v; } |
Использование векторов навигации для передвижения
Имея эти три вектора мы можем их использовать для движения, например, нашей камеры, скажем так:
void CTutorial3D::ProcessUserInput(float fDeltaTime) { float fDelta = fDeltaTime*100; if (GetAsyncKeyState(VK_LEFT)&32768) m_camera.SetPos(m_camera.GetPos() - m_camera.GetRight()*fDelta); if (GetAsyncKeyState(VK_RIGHT)&32768) m_camera.SetPos(m_camera.GetPos() + m_camera.GetRight()*fDelta); if (GetAsyncKeyState(VK_DOWN)&32768) m_camera.SetPos(m_camera.GetPos() - m_camera.GetForward()*fDelta); if (GetAsyncKeyState(VK_UP)&32768) m_camera.SetPos(m_camera.GetPos() + m_camera.GetForward()*fDelta); } |
Собственно, вот Вам и готовое управление игровой камерой.
Раздел: Featured, Теория · Теги: Создание движка
как всегда просто и поучительно спасибо.
ваш блог гороздо интереснее читать, чем книги на ету тему:)
Scripter, YuRik, спасибо
Тут на вас уже ссылка есть в разделе полезных ресурсов.
http://forum.vingrad.ru/forum/topic-252383.html
Думаю, это приятно:)
Да, очень приятно!
Рад, что ресурс оказался кому-то полезен
Для меня эта тема с матрицами тоже пока остается нераскрытой. Прочитал у других авторов и не очень понял. Они и правда используют перемножения матриц. А я нашел вот такое (msdn):
D3DXMatrixRotationX, D3DXMatrixRotationY и другие полезные преобразования. И пока не понятно, чем же эти способы отличаются от авторских? Почему некоторые предпочитают писать свои методы, а не использовать уже существующие в DirectX?
Кому как удобнее – тот так и делает. Тут нет одного универсального способа, который идеально подходил бы во всех случаях. Где-то удобнее “вращать” текущую матрицу, где-то отталкиваться от векторов (вперёд/вверх/в сторону), где-то хранить углы (YawPitchRoll) и т.д.
Эти “способы” ничем не отличаются “от авторских” – это всё один большой способ решить одну и ту же задачу разными путями и при этом то, насколько удобен тот иной путь, зависит от конкретной точки приложения (конкретной игры, конкретной игровой камеры, конкретного управления и так далее).
Вячеслав, возможно вопрос не по теме но, допустим есть карта ландшафта, созданная в 3ds Max, как ее можно “подключить” к игре и там уже в игре перехватывать столкновения с объектами карты, реализовать ходьбу по поверхности, подъемы, спуски, так сказать сделать землю под ногами? Как можно будет различать объекты на карте, дерево это или здание, если они смоделированы таким способом.
И еще один вопрос. Если делать генератор карт, то надо располагать уже существующие модели на генерируемой карте со всеми привязками к текстурам и ландшафт делать так, как генерируются вертексы?
“Подключить” ландшафт к создаваемой вами игре можно, например, в виде модели – если позволяет полиогнальность. Либо ландшафт можно отрендерить (скажем в том же 3d max) ортогональной камерой в карту высот (в т.ч. можно в 32хбитную, если я правильно помню) и использовать эту карту. Разные есть варианты, в общем.
После загрузки ландшафта, соответственно, просто создаёте физическую модель для него и после этого по нему можно будет “ходить”. Либо можно логику реализовать без сторонней физики – там ничего сложного нет, можно легко самостоятельно закодить всё за вечер.
Не очень понял свзяь генерации ландшафта, расстоновки объектов и каких-то (не понял каких) “вертексов”… Объясните подробнее, пожалуйста.
Можете посоветовать где можно почитать о “подключении” ландшафта или как это правильно называется, сам этот процесс, как создания карты, так и ее подключения, так и создания физической модели.
На счет генерации ландшафта, вопрос состоял в том, как его сделать программно? И как там же расставить объекты, в процессе генерации или уже после.
Где почитать о программировании ландшафтов – если честно, не знаю, особо достойных док не встречал. Но, по большому счёту, программирование отображения или физики ландшафта не отличается от любой другой модели (в простейшем случае) – тот же набор треугольников, которые надо просто отрисовать/просчитать коллизии.
Проблемы начинаются когда требуется сделать какие-то более сложные вещи, например, ландшафты очень больших размеров (скажем, площадью от нескольких квадратных км. и больше, или с нерегулярной сеткой). Но вряд ли именно с этого стоит начинать знакомство с ландшафтами – для начала проще всего запрограммировать самый простой вариант (т.е. одна большая модель или несколько меньшего размера стоящих рядом), а потом уже постепенно усложнять.
Если делать ландшафт “по-нормальному”, то для его редактирования проще всего либо написать собственный инструмент, либо использовать сторонние редакторы, заточенные именно под создание/генераци.ю/редактирование именно ландшафтов. Например, такие инструменты как L3DT.
Расставлять объекты, опять же, проще всего в своём собственном редакторе. По своему опыту могу сказать, что если у Вас буду уже реализованные сам ландшафт и функции для отображения/трансформации объекты, то на этой базе создание собственного редактора для расстановки объектов займёт не более пары вечеров (если Вам достаточно минимального функционала).
Спасибо, Вячеслав!
Не за что