Начинаем использовать настоящее 3D

На прошлых уроках мы уже научились создавать и рендерить треугольники (пока еще правда 2D) на экране монитора. Пришло время переходить к трехмерным координатам. Вся трехмерная геометрия основана на использовании матриц, сами матрицы мы создавать не будем, эту обязанность будет выполнять D3D8, вам только нужно уметь мыслить в трех измерениях (хотя это и не обязательно), а желательно знать некоторые основы трехмерной геометрии и трехмерного же пространства.

В общем, переходим прямо к делу...

Главное что у нас появляется при переходе от 2D к 3D это новая координата (Z), поэтому нам необходимо в объявлении наших вершин слегка изменить код :


struct CUSTOMVERTEX { float x, y, z; };
#define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZ )

Соответственно нам необходимо изменить объявление наших вершин для примера :


	CUSTOMVERTEX g_Vertices[] =
	{
		{   0.0f, 100.0f, 0.5f, },
		{ 200.0f, 100.0f, 0.5f, },
		{   0.0f,-100.0f, 0.5f, },

		{  20.0f,-120.0f, 0.5f, },
		{ 220.0f,  80.0f, 0.5f, },
		{ 220.0f,-120.0f, 0.5f, },
	};

	p_d3d_Device->CreateVertexBuffer (6*sizeof(CUSTOMVERTEX), 
				0, D3DFVF_CUSTOMVERTEX, 
				D3DPOOL_MANAGED, &p_VertexBuffer);
	
	VOID* pVertices;
	p_VertexBuffer->Lock (0, sizeof(g_Vertices), (BYTE**)&pVertices, 0);
	memcpy (pVertices, g_Vertices, sizeof(g_Vertices));
	p_VertexBuffer->Unlock();

Подготовительные шаги сделаны.

Теперь возьмемся за ту часть, которая обеспечит нам переход из двухмерного пространства в трехмерное. Здесь мы вводим в рассмотрение три матрицы :

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


D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DXMATRIX matProj;

Далее нам необходимо задать этим матрицам начальные значения :


D3DXMatrixRotationY (&matWorld, 0.0f);
D3DXMatrixLookAtLH (&matView, &D3DXVECTOR3 (0.0f, 0.0f, -500.0f),
			&D3DXVECTOR3 (0.0f, 0.0f, 0.0f),
			&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
D3DXMatrixPerspectiveFovLH (&matProj, D3DX_PI/4, 1.0f, 1.0f, 10000.0f);

В данном конкретном виде мы получаем :

-- ставим вращение сцены равное 0 (я не знаю почему, но не писать данную строчку вообще нельзя - просто ни чего работать не будет)
-- матрица вида - для ее задания используются несколько параметров :

-- точка, где находится наблюдатель,
-- точка на которую смотрит наблюдатель,
-- и верхний вектор зрения наблюдателя.

-- матрица задания проецирования тоже содержит несколько необходимых параметров :

-- первое задаем поле зрение (field of view)
-- затем устанавливаем соотношение геометрических размеров (aspect ratio)
-- два последних параметра задают передний и задний границы отсечения трехмерной геометрии, за этими границами ничего отрисовываться не будет.

После того как вы их создали их нужно установит для вашего устройства D3D8 :


//-----------------------------------------------------------------------------
// Name: SetDeviceParams ()
// Desc:
//-----------------------------------------------------------------------------
void SetDeviceParams (void)
{
	p_d3d_Device->SetTransform (D3DTS_WORLD, &matWorld);
	p_d3d_Device->SetTransform (D3DTS_VIEW, &matView);
	p_d3d_Device->SetTransform (D3DTS_PROJECTION, &matProj);

	p_d3d_Device->SetRenderState (D3DRS_CULLMODE, D3DCULL_NONE);
};

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

Теперь функция рендеринга вашей сцены будет выглядеть примерно так :


//-----------------------------------------------------------------------------
// Name: RenderScreen ()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
void RenderScreen (void)
{
	HRESULT hr;
	hr=p_d3d_Device->TestCooperativeLevel();
	if(hr==D3DERR_DEVICELOST) return;
	if(hr==D3DERR_DEVICENOTRESET) { p_d3d_Device->Reset(&d3dpp); SetDeviceParams (); };

	Transform3D();

	static int c=0 , cc=1;
	if(cc==1) c++;
	if(cc==0) c--;
	if(c==255) cc=0;
	if(c==0) cc=1;

	p_d3d_Device->Clear (0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB (c, 255-c, 0), 1.0f, 0);
	p_d3d_Device->BeginScene ();

	p_d3d_Device->SetVertexShader (D3DFVF_CUSTOMVERTEX);
	p_d3d_Device->SetStreamSource (0, p_VertexBuffer, sizeof(CUSTOMVERTEX));
	p_d3d_Device->DrawPrimitive (D3DPT_TRIANGLELIST, 0, 2);

	p_d3d_Device->EndScene ();
	p_d3d_Device->Present (NULL, NULL, NULL, NULL);
};

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


//-----------------------------------------------------------------------------
// Name: Transform3D ()
// Desc:
//-----------------------------------------------------------------------------
void Transform3D (void)
{
	static float x=0; x+=0.01;

	D3DXMatrixLookAtLH (&matView, &D3DXVECTOR3 (sin(x)*500, 0.0f, -cos(x)*500),
				&D3DXVECTOR3 (0.0f, 0.0f, 0.0f),
				&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
	p_d3d_Device->SetTransform (D3DTS_VIEW, &matView);
};

У вас должно получиться нечто похожее на следующее :

Это пожалуй все на сегодня...



Опубликовал admin
28 Окт, Четверг 2004г.



Программирование для чайников.