Построение стандартных объектов
Библиотека Direct3D располагает рядом встроенных функций для построения простых стандартных трехмерных примитивов (куб, цилиндр, сфера, тор):
- D3DXCreatePolygon // полигон
- D3DXCreateBox // параллелограмм
- D3DXCreateCylinder // цилиндр
- D3DXCreateSphere // сфера
- D3DXCreateTorus // тор
- D3DXCreateTeapot // чайник
При создании объектов таким способом вершины "получают" формат, в котором присутствует положение (D3DFVF_XYZ) и нормаль (D3DFVF_NORMAL). Существует возможность задавать уровень детализации при создании перечисленных выше трехмерных примитивов. Следует заметить, что нормаль к каждой вершине созданного объекта вычисляется автоматически. Рассмотрим их функции создания и визуализации. Для работы с подобными примитивами необходимо объявить переменную интерфейсного типа ID3DXMesh, в которой и будет "храниться" трехмерный объект. Визуализация созданного объекта осуществляется вызовом метода DrawSubset интерфейса ID3DXMesh.
Функция создания полигона (правильного многоугольника):
D3DXCreatePolygon( ссылка на устройство вывода, длина стороны полигона, количество сторон полигона, результат, указатель на смежные треугольники);
Ниже приведен пример создания и визуализации трехмерного объекта – полигона.
C++ |
// объявление переменной LPD3DXMESH polygon; // создание объекта полигон D3DXCreatePolygon( device, 0.5, 10, &polygon, NULL); // визуализация polygon->DrawSubset(0); |
Pascal |
// объявление переменной var polygon: ID3DXMesh; // создание объекта полигон D3DXCreatePolygon(device, 0.5, 10, polygon, nil); // визуализация polygon.DrawSubset(0); |
Ниже приведены примеры построения полигонов с разными значениями второго и третьего параметра рассмотренной функции.
Длина стороны = 0.5
Количество сторон = 10 | Длина стороны = 2
Количество сторон = 3 | Длина стороны = 0.1
Количество сторон = 36 | |||
Функция вывода параллелепипеда
D3DXCreateBox( ссылка на устройство вывода, ширина, высота, глубина, результат, указатель на смежные треугольники);
Ниже приведен пример создания и визуализации трехмерного объекта – полигона.
C++ | // объявление переменной LPD3DXMESH box; // создание объекта D3DXCreateBox( device, 1.0f, 0.5f, 2.0f, &box, NULL); // визуализация box->DrawSubset(0); |
Pascal | // объявление переменной var box: ID3DXMesh; // создание объекта D3DXCreateBox(device, 1, 0.5, 2, box, nil); // визуализация box.DrawSubset(0); |
ширина = 1 высота = 0.5 глубина = 2 | ширина = 1 высота = 1 глубина = 1 | ширина = 0.5 высота = 2 глубина = 1 |
D3DXCreateCylinder( ссылка на устройство радиус первого основания радиус второго основания высота цилиндра количество разбиений "по радиусу" количество разбиений "по длине" результат указатель на смежные треугольники);
C++ | LPD3DXMESH cylinder; D3DXCreateCylinder(device, 0.2f, 0.2f, 1, 16, 3, &cylinder, NULL); cylinder->DrawSubset(0); |
Pascal | var cylinder: ID3DXMesh; D3DXCreateCylinder(device, 0.2, 0.2, 1, 16, 3, cylinder, nil); cylinder.DrawSubset(0); |
Первое основание = 0.2 Второе основание = 0.2 Разбиений по радиусу = 16 | Первое основание = 0.4 Второе основание = 0.2 Разбиений по радиусу = 16 | Первое основание = 0.4 Второе основание = 0 Разбиений по радиусу = 6 |
D3DXCreateSphere( ссылка на устройство, радиус сферы, разбиений "по радиусу", // число апельсиновых долек разбиений "вдоль", // результат, указатель на смежные треугольники);
Разбиений по радиусу = 6, вдоль = 32 | Разбиений по радиусу = 32, вдоль = 6 |
C++ | LPD3DXMESH sphere; D3DXCreateSphere(device, 1.0f, 16, 16, &sphere, NULL); sphere->DrawSubset(0); |
Pascal | var sphere: ID3DXMesh; D3DXCreateSphere(device, 1, 16, 16, sphere, nil); sphere.DrawSubset(0); |
D3DXCreateTorus( ссылка на устройство, внутренний радиус тора, внешний радиус тора, количество разбиений в поперечном сечении, количество разбиений по кругу, результат, указатель на смежные треугольники);
Разбиений в сечение = 6 Разбиений по кругу = 32 | Разбиений в сечение = 32 Разбиений по кругу = 6 |
table class="xml_table" cellpadding="2" cellspacing="1">
LPD3DXMESH torus; D3DXCreateTorus(device, 0.2f, 0.8f, 32, 6, &torus, NULL); torus->DrawSubset(0);
var torus: ID3DXMesh; D3DXCreateTorus(device, 0.2, 0.8, 32, 6, torus, nil);
torus.DrawSubset(0);
D3DXCreateTeapot( ссылка на устройство, результат, указатель на смежные треугольники);
Это единственный примитив, для которого отсутствует возможность задать уровень детализации.
C++ | LPD3DXMESH teapot; D3DXCreateTeapot(device, &teapot, NULL); teapot->DrawSubset(0); |
Pascal | var teapot: ID3DXMesh; D3DXCreateTeapot(device, teapot, nil); teapot.DrawSubset(0); |
light.Ambient = D3DXCOLOR(0.3f, 0,0,0); | |
light.Diffuse = D3DXCOLOR(0.5f, 0.0, 0,0); light.Ambient = D3DXCOLOR(0.2f, 0,0,0); | |
light.Diffuse = D3DXCOLOR(0.5, 0.0, 0,0); light.Ambient = D3DXCOLOR(0.2, 0,0,0); light.Specular = D3DXCOLOR(0.3,0,0.0,0); |
C++ | device->SetRenderState( D3DRS_SPECULARENABLE, TRUE ); |
Pascal | device.SetRenderState(D3DRS_SPECULARENABLE, 1); |
C++ | D3DMATERIAL9 material; D3DLIGHT9 light0, light1, light2; ZeroMemory( &material, sizeof(D3DMATERIAL9) ); material.Diffuse=D3DXCOLOR(1.0f, 1.0f, 1.0f, 0.0f); ZeroMemory( &light0, sizeof(D3DLIGHT9) ); light0.Type = D3DLIGHT_POINT; light0.Diffuse = D3DXCOLOR(0.5f, 0.0f, 0.0f, 0.0f); light0.Position = D3DXVECTOR3(4.0f, 0.0f, 0.0f); … ZeroMemory( &light1, sizeof(D3DLIGHT9) ); light1.Type = D3DLIGHT_POINT; light1.Diffuse = D3DXCOLOR(0.0f, 0.5f, 0.0f, 0.0f); light1.Position = D3DXVECTOR3(0.0f, 0.0f, -4.0f); … ZeroMemory( &light2, sizeof(D3DLIGHT9) ); light2.Type = D3DLIGHT_POINT; light2.Diffuse = D3DXCOLOR(0.0f, 0.0f, 0.5f, 0.0f); light2.Position = D3DXVECTOR3(-4.0f, 0.0f, 0.0f); device->SetRenderState( D3DRS_LIGHTING, TRUE ); ... // процедура рендеринга device->SetLight( 0, &light0 ); device->LightEnable( 0, TRUE ); device->SetLight( 1, &light1 ); device->LightEnable( 1, TRUE ); device->SetLight( 2, &light2 ); device->LightEnable( 2, TRUE ); |
Pascal | var material: TD3DMaterial9; light0, light1, light2: TD3DLight9; ZeroMemory(@material,SizeOf(TD3DMaterial9)); material.Diffuse:=D3DXColor(1,1,1,0); light0._Type:=D3DLIGHT_POINT; light0.Diffuse:=D3DXColor(0.5, 0.0, 0, 0); light0.Position:=D3DXVector3(4,0,0); … light1._Type:=D3DLIGHT_POINT; light1.Diffuse:=D3DXColor(0.0, 0.5, 0, 0); light1.Position:=D3DXVector3(0,0,-4); … light2._Type:=D3DLIGHT_POINT; light2.Diffuse:=D3DXColor(0.0, 0.0, 0.5, 0); light2.Position:=D3DXVector3(-4,0,0); … device.SetRenderState(D3DRS_LIGHTING, 1); // процедура рендеринга device.SetLight(0,light0); device.LightEnable(0,true); device.SetLight(1,light1); device.LightEnable(1,true); device.SetLight(2,light2); device.LightEnable(2,true); |
Сложные ( содержащие десятки тысяч вершин) объекты, как правило, создаются в профессиональных трехмерных редакторах (3D Studio, Maya, LightWave, и т.п.). Библиотека Direct3D содержит средства для загрузки и визуализации моделей, содержащихся в x-файлах. Х-файл – файл, содержащий в себе данные о трехмерном объекте (координаты вершин, материалы, нормали, текстуры и анимацию). Вначале необходимо объявить нужные переменные.
C++ | LPD3DXMESH mesh; |
Pascal | var mesh: ID3DXMesh; |
D3DXLoadMeshFromX( путь до файла на диске, набор флагов, указатель на устройство вывода, информация о смежных треугольниках, данные о материалах модели, данные об эффектах модели, количество материалов в модели, результат ).
В простейшем случае (если модель не содержит информации о материалах, текстурах, смежности граней) параметры с четвертого по седьмой включительно выставляют в NULL. Ниже приведен пример загрузки модели из Х-файла.
C++ | D3DXLoadMeshFromX("ship.x", D3DXMESH_MANAGED, device, NULL, NULL, NULL, NULL, &mesh); |
Pascal | D3DXLoadMeshFromX('ship.x', D3DXMESH_MANAGED, device, nil, nil, nil, nil, mesh); |
C++ | mesh->DrawSubset(0); |
Pascal | mesh.DrawSubset(0); |