Графика DirectX в Delphi
Шрифт:
end;
Размеры буфера глубины будут автоматически определяться системой при каждом изменении размеров окна.
При очередной перерисовке кадра теперь должен очищаться не только буфер кадра, но и подключенный буфер глубины. Предпоследний параметр метода clear объекта устройства - значение, которым заполняется буфер глубины. Этим значением должна быть единица, фон экрана бесконечно удален в пространстве:
FD3DDevice.Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,
$00FFFFFF, 1.0, 0) ;
Для
SetRenderState(D3DRS_ZENABLE, D3DZBJTRUE);
Флагом для этого состояния может быть и обычная булева константа.
Сейчас нам необходимо перейти к следующему примеру, проекту каталога Ех03, после его запуска на экране появляется вращающийся чайник и стрелки осей координат (рис. 9.4).
Буфер вершин заполняется данными для трех трехмерных объектов: цилиндра, конуса и чайника:
function TfrmD3D.InitVB : HRESULT;
const
radius =0.1; // Радиус цилиндра
var
Vertices : ^TCustomVertex;
hRet : HRESULT;
theta : Single;
i : Integer;
t : TextFile; // Данные модели хранятся в текстовом файле
wX, wY, wZ : Single;
egin hRet := FD3DDevice.CreateVertexBuffer((100 + 51 * 2 + 6322 * 3) *
SizeOf(TCustomVertex), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, FD3DVB);
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
hRet := FDSDDevice.SetStreamSource(0, FD3DVB, SizeOf(TCustomVertex));
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
hRet := FD3DDevice.SetVertexShader(D3DFVF_CUSTOMVERTEX);
if Failed(hRet) then begin
Result := hRet;
Exit; end; hRet := FD3DVB.Lock(0, (100 + 51 * 2 + 6322 * 3)*
SizeOf(TCustomVertex), PByte(Vertices), 0);
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// 100 вершин цилиндра, по часовой стрелке
for i ;= 49 downto 0 do begin
theta := 2 * Pi * i / 49;
Vertices.X := sin(theta) * radius;
Vertices.Y := -1;
Vertices.Z := cos(theta) * radius;
Vertices.nX := sin(theta);
Vertices.nY := 0;
Vertices.nZ := cos(theta);
Inc(Vertices);
Vertices.X := sin(theta) * radius;
Vertices.Y := 1;
Vertices.Z := cos(theta) * radius;
Vertices.nX := sin(theta);
Vertices.nY := 0;
Vertices.nZ := cos(theta);
Inc(Vertices);
end;
//
Vertices.X := 0.0;
Vertices.Y := 0.0;
Vertices.Z := 1.0;
Vertices.nX := 0.0;
Vertices.nY := 0.0;
Vertices.nZ := 1.0;
Inc(Vertices) ;
// Треугольники, образующие конус
for i := 0 to 49 do begin
theta := 2 * Pi * i / 49;
Vertices.X := cos(theta);
Vertices.Y := sin(theta);
Vertices.Z := 0.0;
Vertices.nX := cos(theta);
Vertices.nY := sin(theta);
Vertices.nZ := 1.0;
Inc(Vertices);
end;
// Центр донышка конуса
Vertices.X := 0.0;
Vertices.Y := 0.0;
Vertices.Z := 0.0;
Vertices.nX := 0.0;
Vertices.nY := 0.0;
Vertices.nZ := -1.0;
Inc(Vertices);
// Круг, закрывающий конус
for i := 0 to 49 do begin
theta := 2 * Pi * i / 49;
Vertices.X := sin(theta);
Vertices.Y := cos(theta);
Vertices.Z := 0.0;
Vertices.nX := 0.0;
Vertices.nY := 0.0;
Vertices.nZ := -1.0;
Inc(Vertices);
end;
// Считьшаем данные модели из файла
AssignFile (t, 'teapot.txt');
Reset (t) ;
while not EOF(t) do begin
Readln (t, wX); // Нормаль к треугольнику
Readln (t, wY);
Readln (t, wZ) ;
Readln (t, Vertices.X); // Первая вершина треугольника
Readln (t, Vertices.Y);
Readln (t, Vertices.Z);
Vertices.nX := wX;
Vertices.nY := wY;
Vertices.nZ := wZ;
Inc (Vertices);
Readln (t, Vertices.X); // Вторая вершина треугольника
Readln (t, Vertices.Y);
Readln (t, Vertices.Z);
Vertices.nX := wX;
Vertices.nY := wY;
Vertices.nZ := wZ;
Inc (Vertices);
Readln (t, Vertices.X) ; // Последняя вершина треугольника
Readln (t, Vertices.Y);
Readln (t, Vertices.Z);
Vertices.nX := wX;
Vertices.nY := wY;
Vertices.nZ := wZ;
Inc (Vertices); end;
CloseFile (t); Result := FD3DVB.Unlock;
end;
Цилиндр радиуса 0.1 и высотой 2 строится вокруг оси Y, а конус единичной высоты - вокруг оси Z. О том, как получены точки модели, мы поговорим чуть позже, сейчас же я должен сообщить, что вершины треугольников модели перечисляются против часовой стрелки.
Текущие параметры матриц вида и проекций хранятся в следующих переменных: