Программирование 3D-игр в DirectX на Delphi
 
         
    [Главная] [Новости] [Статьи] [Игры] [Проекты] [Автор]  
         
    [Архив новостей]    
         
  [Форум] на форуме можно задать вопрос, посмотреть ответы на часто задаваемые вопросы  
         
  Основы 3D-программирования DirectX9 в Delphi 2006: теоретические и практические основы создания игр.  
     
     
Здравствуйте! Вы попали на информационно-образовательный сайт посвященный информатике, информационным технологиям и компьютерным играм. Подробнее о целях и задачах сайта в разделе Главная. [English version of this page here...]
 
[Базовые уроки по DirectX] [Основы DirectMusic на Delphi] [Основы DirectInput8 на Delphi] [Основы DirectSound8 на Delphi]
[Разработка компьютерной игры] [Пример игры Donuts3D] [Delphi DirectX]
 
Что такое Delphi DirectX ?
     
  [назад] [далее] [к содержанию]  
     
  16/05/2009  
     
  Продолжаем разбирать пример MultiAnimation из DirectX SDK 9  
     
  function CMyD3DApplication.FrameMove: HRESULT;
var
i: Integer;
begin
// we only need to call the animation routine 60 times per second
//выполнение анимации происходит только 60 раз в секунду, т.е. делая это чаще мы можем повысить точность и плавность анимации, но ценой снижения производительности приложения и наоборот - делае это реже можно повысить производительность, но ценой качества анимации
if (m_fTime - m_fLastAnimTime > (1.0 / 60.0)) then
begin
for i:= 0 to m_v_pCharacters.Count - 1 do
m_v_pCharacters[i].Animate(m_fTime - m_fLastAnimTime);

m_fLastAnimTime := m_fTime;
end;

// Update the camera //обновляется положение камеры
m_Camera.FrameMove(m_fElapsedTime);

Result:= S_OK;
end;

 
     
 

из метода Render рассмотрим только ту часть кода, которая отвечает за отрисовку игровой сцены и персонажа -

function CMyD3DApplication.Render: HRESULT;

{...}

// set up the camera //настройка камеры

// are we following a tiny, or an independent arcball camera? //камера следует за персонажем или она независима?
if (m_dwFollow = $ffffffff) then
//если следует за персонажем, то вычисляется новое направление источника освещения
begin
// Light direction is same as camera front (reversed)
// vLightDir := -m_Camera.GetWorldAhead;
D3DXVec3Scale(vLightDir, m_Camera.GetWorldAhead, -1);

// set static transforms
mxView := m_Camera.GetViewMatrix^;
//формируется матрица вида из камеры и проекционная матрица - представляющая итог вывода на плоскую поверхность экрана (проецирование)
mxProj := m_Camera.GetProjMatrix^;
m_pd3dDevice.SetTransform(D3DTS_VIEW, mxView);
//данные матрицы задают соответствующие трансформации
m_pd3dDevice.SetTransform(D3DTS_PROJECTION, mxProj);
vEye := m_Camera.GetEyePt;
//определяется положение ока (глаза)
end else
begin
// set follow transforms
//в случае следования за персонажем
pChar := m_v_pCharacters[m_dwFollow];
//ссылка на персонаж, за которым следует камера

pChar.GetPosition(vCharPos); //положение персонажа в сцене
pChar.GetFacing(vCharFacing);
//направление взгляда персонажа (в какую сторону смотрит персонаж)
vEye := D3DXVector3(vCharPos.x, 0.25, vCharPos.z);
//положение ока
vAt:= D3DXVector3(vCharPos.x, 0.0125, vCharPos.z);
//LookAt - куда смотрит око
vUp:= D3DXVector3(0.0, 1.0, 0.0);
//3ий вектор, определяющий положение камеры (высота)

//так как точная ориентация любого объекта в 3D-пространстве определяется именно тремя векторами, то и для камеры применяется 3 вектора: vEye, vAt, vUp

//далее выполняется небольшой пересчет полученных векторов (чтобы камера не оказалась как бы внутри персонажа)
vCharFacing.x := vCharFacing.x * 0.25; vCharFacing.y := 0.0; vCharFacing.z := vCharFacing.z * 0.25;
// vEye := vEye - vCharFacing;
D3DXVec3Subtract(vEye, vEye, vCharFacing);
// vAt := vAt + vCharFacing;
D3DXVec3Add(vAt, vAt, vCharFacing);

D3DXMatrixLookAtLH(mxView, vEye, vAt, vUp); //по данным векторам получаем матрицу вида из камеры
m_pd3dDevice.SetTransform(D3DTS_VIEW, mxView);
//задаем ее в качестве матрицы трансформации вида

D3DXMatrixPerspectiveFovLH(mxProj, D3DXToRadian(60.0), m_fAspectRatio, 0.1, 100.0); //получаем проекционную матрицу используя данный угол обзора, соотношение, передний и задний план
m_pd3dDevice.SetTransform(D3DTS_PROJECTION, mxProj);
//полученную матрицу задаем в качестве матрицы проекционной трансформации

// Set the light direction and normalize //вычисляем направление источника света путем вычитания vAt - vEye (имеется в виду вычитание векторов, а не обычное вычитание чисел)
D3DXVec3Subtract(vLightDir, vEye, vAt);
D3DXVec3Normalize(vLightDir, vLightDir);
//нормализуем полученный вектор (т.е делаем его длину не превышающей 1)

Если Ваши познания в векторной математике незначительны или совсем отсутствуют, то кое-что можно прочесть в статье Основы теории векторов
end;

pEffect := m_MultiAnim.GetEffect; //получаем ссылку на объект эффекта (fx)
if (pEffect <> nil) then
begin
// set view-proj
D3DXMatrixMultiply(mx, mxView, mxProj);
//перемножаем матрицу вида на проекционную матрицу
pEffect.SetMatrix('mViewProj', mx);
//результат передаем как результирующую матрицу для обработки эффекта

// Set the light direction so that the //устанавливаем направление источника света так, чтобы видимая сторона (элементов моделей игровой сцены) была освещена
// visible side is lit.
v:= D3DXVector4(vLightDir.x, vLightDir.y, vLightDir.z, 1.0);
//Получаем 4D-вектор (кватернион) и задаем его в качестве вектора направления освещения в эффекте
pEffect.SetVector('lhtDir', v);

pEffect:= nil; //больше ссылка на объект эффекта нам не требуется, освобождаем ее
end;

// set the fixed function shader for drawing the floor //используем фиксированный шейдер для рисования пола
m_pd3dDevice.SetVertexShader(nil);
m_pd3dDevice.SetFVF(m_pMeshFloor.GetFVF);

// draw the floor //рисуем модель пола с данной текстурой, материалом, положение пола в 3d-пространстве задаем матрицей m_mxFloor
m_pd3dDevice.SetTexture(0, m_pTxFloor);
m_pd3dDevice.SetMaterial(m_MatFloor);
m_pd3dDevice.SetTransform(D3DTS_WORLD, m_mxFloor);
m_pMeshFloor.DrawSubset(0);

// draw each tiny //рисуем персонажей
for i:= 0 to m_v_pCharacters.Count - 1 do
with m_v_pCharacters[i] do
begin
// set the time to update the hierarchy
AdvanceTime(m_fElapsedTime, @vEye);
//обновляем матрицы для элементов иерархии в соответствии с текущим временем
// draw the mesh
Draw;
//рисуем меш персонажа
end;

 
     
  Итак, в первом приближении Вам должно быть понятно как происходит работа с анимированной моделью с несколькими наборами анимаций  
     
  Чтобы лучше уяснить себе работу с анимированными моделями, а заодно и более глубоко исследовать исходный код примера MultiAnimation мы переходим к написанию собственного класса для работы с анимированной моделью, кроме того, такой класс будет полезен не только в учебных целях, но и в любом реальном игровом проекте.  
     
  [назад] [далее] [к содержанию]  
       
 

 

Обновления и новости о развитии Delphi DirectX проекта
смотри на сайтах:

http://www.megainformaticsite.pochta.ru

http://www.megainformatic.boom.ru

http://www.megainformatic.narod.ru

 

   
       
     
 

по всем вопросам пишите на megainformatic@mail.ru или оставьте сообщение на форуме

 
     
   Обмен ссылками  
     
     
             
 
 
         
(с) МЕГА ИНФОРМАТИК 2006-2009

 

Hosted by uCoz