Михаил Краснов - Графика DirectX в Delphi
- Название:Графика DirectX в Delphi
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Михаил Краснов - Графика DirectX в Delphi краткое содержание
Графика DirectX в Delphi - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
x := random(NumX - 3) + 1;
z := random(NumZ - 3) + 1;
Land[x,z].h := random(500);
end;
// Усредняем высоты соседних точек, чтобы получить плавные холмы
for k := 1 to FlatLand do
for i:= 2 to NumX. do
for j := 2 to NumZ do
Land[i,j].h := (Land[i,j].h +
Land[(i + 1) mod NumX,j].h +
Land[i - 1, j].h +
Land[i, (j + 1) mod NumZ].h +
Land[i, j - 1].h) / 5;
// Приводим данные к удобному виду, задаем цвет вершин
for i := 1 to NumX do
for j := 1 to NumZ do
with Land[i,j] do begin
h := h / 100; if h > 0.85 then h := 0.85;
if h > 0.4 // Высокие вершины окрашиваем белым цветом
then Land[i,j].Color := $00FFFFFF else
if h > 0.2 // Точки чуть ниже - коричневым
then Land[i,j].Color := $00804000 else
if h > 0.1 // Вершины еще ниже - желтые
then Land[i,j].Color := $00FFFF00
// Точки на равнине - зеленые
else Land[i,j].Color := $0000FF00;
end;
// Рассчитываем нормали к вершинам
for i := 1 to NumX - 1 do
for j := 1 to NumZ do
CalcNormals (D3DVector (i * Step, Landfi, j - 1].h, (j - 1) * Step),
D3DVector (i * Step, Land[i, j].h, j * Step),
DSDVector ((i + 1) * Step, Landfi + 1, j - l].h,
(j - 1) * Step), Land[i, j].VecNormal);
end;
Данные модели считываются из текстового файла. В буфере вершин первые четыре вершины отводятся для построения отдельного квадрата ландшафта:
function TfrmDSD.InitVB : HRESULT;
var
Vertices : ^TCustomVertex;
hRet : HRESULT;
t : TextFile;
wrkVec : TD3DVector;
begin
FDSDDevice.CreateVertexBuffer(20665 * SizeOf(TCustomVertex), 0,
DSD FVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, FD3DVB);
FD3DDevice.SetStreamSource(0, FD3DVB, SizeOf(TCustomVertex));
FD3DVB.Lock(0, 20665 * SizeOf(TCustomVertex), PByte(Vertices), 0);
Inc (Vertices); // Первые четыре вершины отводятся для построения
Inc (Vertices); // отдельного квадрата ландшафта
Inc (Vertices);
Inc (Vertices);
AssignFile (t, 'Boeing.txt1);
Reset (t);
while not EOF(t) do begin
Readln (t, wrkVec.X); // Считываем вектор нормали
Readln (t, wrkVec.Y);
Readln (t, wrkVec.Z);
// Считываем вершины очередного треугольника
Readln (t, Vertices.X);
Readln (t, Vertices.Y);
Readln (t, Vertices.Z); .
// Исходные данные модели масштабируются
Vertices.X := Vertices.X / 3;
Vertices.Y := Vertices.Y / 3;
Vertices.Z := Vertices.Z / 3;
Vertices.normVector := wrkVec;
Vertices.Color := $00808080; // Цвет - серебристый
Inc (Vertices);
Readln (t, Vertices.X);
Readln (t, Vertices.Y);
Readln (t, Vertices.Z);
Vertices.X := Vertices.X / 3;
Vertices.Y := Vertices.Y / 3;
Vertices.Z := Vertices.Z / 3;
Vertices.normVector := wrkVec;
Vertices.Color := $00808080;
Inc (Vertices);
Readln (t, Vertices.X);
Readln (t, Vertices.Y);
Readln (t, Vertices.Z) ;
Vertices.X := Vertices.X / 3;
Vertices.Y := Vertices.Y / 3;
Vertices.Z := Vertices.Z / 3;
Vertices.normVector := wrkVec;
Vertices.Color := $00808080;
Inc (Vertices);
end;
CloseFile (t); FD3DVB.Unlock;
Result := FD3DDevice.SetVertexShader(D3DFVF_CUSTOMVERTEX);
end;
После считывания данных модели поворачиваем ее вокруг собственных осей:
procedure TfrmD3D.FormCreate(Sender: TObject);
var
hRet : HRESULT;
matView, matProj : TD3DMatrix;
matWrkl, matWrk2 : TDSDMatrix;
begin
Randomize; // Ландшафт генерируется каждый раз по-новому
ShowCursor (False); // Устанавливаем полноэкранный режим
hRet := InitD3D;
if Failed (hRet) then ErrorOut ('InitD3D', hRet);
hRet := InitVB;
if Failed (hRet) then ErrorOut ('InitVertex', hRet);
SetupLights;
// Поворачиваем самолет
SetRotateXMatrix(matWrkl, Pi / 2);
SetRotateZMatrix(matWrk2, Pi);
SetTranslateMatrix (matAirplan, 7.0, 2.0, 5.0);
// Первоначальная матрица трансформаций для самолета
matAirplan := MatrixMul (matAirplan, MatrixMul (matWrk2, matWrkl));
GenLand; // Генерируем ландшафт пейзажа
SetViewMatrix(matView, D3DVector(16, 2.5, 5),
D3DVector(0, 0, 5), D3DVector(0, 1, 0));
FD3DDevice.SetTransform(D3DTS_VIEW, matView);
SetProjectionMatrix(matProj, 1, 1, 1, 15);
FD3DDevice.SetTransform(D3DTS_PROJECTION, matProj);
end;
Ландшафт рисуется на основе данных массива, по отдельным квадратикам:
arocedure TfrmDSD.DrawArea(const x, у : Integer);
var
Vertices : ATCustomVertex;
b egin
FD3DVB.Lock(0, 4 * SizeOf(TCustomVertex), PByte(Vertices), 0) ;
Vertices.X := x * Step;
Vertices.Y := Land[x, у - 1].h;
Vertices.Z := (y - 1) * Step;
Vertices.normVector := Land[x, у - 1].VecNormal;
Vertices.Color := Land[x, у - 1].Color;
Inc (Vertices);
Vertices.X := x * Step;
Vertices.Y := Landfx, y].h;
Vertices.Z := у * Step;
Vertices.normVector := Land[x, y].VecNormal;
Vertices.Color := Landfx, y].Color;
Inc (Vertices);
Vertices.X := (x + 1) * Step;
Vertices.Y := Landfx + 1, у - 1].h;
Vertices.Z := (y - 1) * Step;
Vertices.normVector := Land[x + 1, у - 1].VecNormal;
Vertices.Color := Land[x + 1, у - 1].Color;
Inc (Vertices);
Vertices.X := (x + 1) * Step;
Vertices.Y := Land[x +1, y].h;
Vertices.Z := у * Step;
Vertices.normVector := Land[x + 1, y].VecNormal;
Vertices.Color := Land[x + 1, y].Color;
FD3DVB.Unlock;
FD3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2) ;
end;
function TfrmD3D.Render : HRESULT;
var
hRet : HRESULT;
i, j :Integer;
begin
// Экран окрашивается голубоватым цветом
FD3DDevice.Clear(0, nil, D3DCLEARJTARGET or D3DCLEAR_ZBUFFER,
$00000FFF, 1.0, 0);
FD3DDevice.BeginScene; with FD3DDevice do begin
SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
// Треугольники ландшафта перечисляются по часовой стрелке
SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
// Вершины ландшафта сгенерированы в мировой системе координат
SetTransform(D3DTS_WORLD, IdentityMatrix);
end;
// Выводим квадратики ландшафта
for j := 2 to NumZ - 1 do
for i := 1 to NumX - 5 do DrawArea(i,j);
with FD3DDevice do begin
// Устанавливается матрица трансформаций самолета
SetTransform(D3DTS_WORLD, matAirplan);
// Вершины модели перечисляются против часовой стрелки
SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
// Данные располагаются, начиная с четвертой вершины
DrawPrimitive(D3DPT_TRIANGLELIST, 4, 20661 div 3);
end;
FD3DDevice.EndScene;
Result := FDSDDevice.Present(nil, nil, 0, nil) ;
end;
После того, как нарисован самолет, текущей трансформацией мировой матрицы остается матрица трансформаций нашей модели, поэтому перед рисованием ландшафта задаем здесь матрицу идентичности.
При каждой перерисовке кадра ландшафт циклически сдвигается, а самолет поворачивается вокруг своей оси на небольшой угол:
procedure MoveLand; // Циклическое движение пейзажа
var
i, j : Integer;
TempLand : array [l..NumX] of LandParam; // Вспомогательный массив begin
// Запомнили строку массива ландшафта
for i := 1 to NuraX do TempLand[i] := Land[i,NumZ];
// Сдвигаем ландшафт
for j := NumZ downto 2 do
for i := 1 to NumX do Land[i,j] := Landfi,j-1]; // Круговое появление последней строки массива
for i := 1 to NumX do Land[i,l] := TempLand[i];
end;
procedure TfrmDSD.ApplicationEventslIdle(Sender: TObject;
var Done: Boolean);
var
matWrk : TD3DMatrix;
begin
if FActive then begin
Render; // Нарисовали кадр
MoveLand; // Передвинули ландшафт
SetRotateYMatrix(matWrk, 0.1); // Матрица для небольшого поворота
matAirplan := MatrixMul (matAirplan, matWrk); // Поворот самолета
end;
Done := False;
end;
Для оптимизации в коде программы я матрицу поворота вычисляю один раз.
Обратите внимание на то, что в программе используется два направленных источника света, и, самое главное, на то, что формат вершин с указанием нормали и цвета позволяет воспроизводить объекты без дополнительных ухищрений. В самом деле, в программе отсутствуют материалы, и такой способ окрашивания примитивов является самым простым и быстрым.
Однако в этом примере мы сильно перерасходуем память, ведь две тысячи треугольников модели окрашиваются одним цветом, а для каждой вершины модели мы вынуждены задавать цвет. При использовании же материала память сильно экономится, но мы не получим тогда сглаживание цветов для треугольников ландшафта.
Пример проекта каталога Ех09 подсказывает возможное решение. Здесь на фоне того же ландшафта, что и в предыдущем примере, гордо парит орел (рис. 9.10).

Вкратце суть решения можно передать следующими словами: в программе применяются два буфера вершин различных форматов, один из которых не имеет цветового компонента:
type
TCUSTOMVERTEXLand = packed record
Читать дальшеИнтервал:
Закладка: