Графика DirectX в Delphi
Шрифт:
Заполняются целиком матрицы трансформаций сфер и корабля один раз, при инициализации:
procedure TfrmD3D.FormCreate(Sender: TObject);
var
hRet : HRESULT;
raatView, matProj : TDSDMatrix;
i : Integer; matWrk : TD3DMatrix;
begin
ShowCursor (False);
hRet := OnCreateDevice; // Инициализация библиотеки
DirectInput if Failed (hRet) then ErrorOut ('InitDirectlnput', hRet);
hRet := InitDSD;
if Failed (hRet) then ErrorOut ('InitDSD1, hRet);
hRet := InitVB;
if Failed (hRet) then ErrorOut ('InitVertex', hRet);
SetupLights;
//
for i := 0 to NumSpheres - 1 do with Spheres [i] do begin
// Положение по оси Z, расстояние до космического корабля
Z := random * 80 - 40;
Radius := random * 0.1+0.1; // Размер сферы
SetScaleMatrix(matSphere, Radius, Radius, Radius);
// Вспомогательная матрица трансформаций
SetTranslateMatrix (matWrk, random * 20 - 10, random * 20 - 10, Z);
// Окончательная инициализация матрицы трансформаций сферы
matSphere := MatrixMul (matSphere, matWrk);
// Инициализация материала сферы
MaterialSphere := InitMaterial(random * 0.5+0.5, random * 0.5+0.5,
random * 0.5 + 0.5, 0) ;
end;
// Космический корабль - золотистого цвета MaterialXWing := InitMaterial(1.О, 1.0, 0.0, 0); // Поворот модели по оси X SetRotateXMatrix(matXWing, -Pi /2);
// Видовая матрица и матрица проекций устанавливается один раз
SetViewMatrixfmatView, D3DVector(0, 0, -5), D3DVector(0, О, О), D3DVector(0, I, 0));
FD3DDevice.SetTransform(D3DTS_VIEW, matview);
SetProjectionMatrixdnatProj, 1, 1, 1, 100);
FD3DDevice.SetTransform(D3DTS_PROJECTION, matProj);
end;
При движении сферы в пространстве и при генерации нового ее положения не обращаемся к операциям перемножения матриц, а изменяем значение только элементов четвертой строки матрицы трансформации сферы:
procedure TfrmD3D.DrawScene;
var
i : Integer;
begin
// Рисуем космический корабль
with FDSDDevice do begin
SetMaterial(MaterialXWing); // Устанавливаем материал
// Матрица трансформаций рассчитана раньше
SetTransform(D3DTS_WORLD, matXWing);
// Модель корабля нарисована по часовой стрелке
SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
// Вывод треугольников модели DrawPrimtive(D3DPT_TRIANGLELIST, 0, 2498);
// Сфера нарисована против часовой стрелки
SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
end;
// Вывод массива сфер
for i := 0 to NumSpheres - 1 do begin
with FDSDDevice do begin
SetMaterial(Spheres [i].MaterialSphere);
SetTransform(D3DTS_WORLD, Spheres [i].matSphere);
DrawPrimitive(D3DPT_TRIANGLELIST, 7494, 110);
end;
with Spheres [i] do begin
//
Z := Z - 0.3;
// He перемножаем матрицы, меняем значение только одного элемента
Spheres [i].matSphere._43 := Z;
// Сфера улетела за пределы экрана
if Z < -20 then begin
// Генерируем новое значение координаты X сферы
matSphere._41 := random * 20 - 10;
// Генерируем новое значение координаты У сферы
matSphere._42 := random * 20-10;
Z := 50 + random (10); // Новое значение координаты Z
matSphere. 43 := Z;
// Генерируем новый материал сферы MaterialSphere := InitMaterial (random * 0.5 -t- 0.5,
random * 0.5 + 0.5, random * 0.5 + 0.5, 0);
end;
end;
end;
end;
Для максимального ускорения работы приложения из кода удалены все проверки успешности выполнения операций для каждого обновления кадра. Обратите внимание, что на сцене присутствует три источника света для освещения корабля с различных сторон.
При перемещении курсора мыши меняются значения элементов матрицы трансформаций космического корабля, при нажатых кнопках мыши происходит поворот корабля вокруг оси Y:
function TfrmDSD.ReadlmmediateData : HRESULT;
var
hRet : HRESULT;
dims2 : TDIMOUSESTATE2;
matRotateY : TD3DMatrix;
begin
ZeroMemory(@dims2, SizeOf(dims2));
hRet := DIMouse.GetDeviceState(SizeOf(TDIMOUSESTATE2), @dims2) ;
if Failed (hRet) then begin
hRet := DIMouse.Acquire;
while hRet = DIERR__INPUTLOST do
hRet := DIMouse.Acquire;
end;
// Нажата левая кнопка мыши, вращение корабля
if dims2.rgbButtons[0] = 128 then begin
SetRotateYMatrix(matRotateY, 0.1);
matXWing := MatrixMul (matXWing, matRotateY);
end;
// Правая кнопка мыши, вращение в противоположную сторону
if dims2.rgbButtons[1] = 128 then begin
SetRotateYMatrix(matRotateY, -0.1);
matXWing := MatrixMul (matXWing, matRotateY);
end;
// Движение курсора мыши, перемещение корабля по осям X и Y
matXWing._41:= matXWing._41 + 0.01 * dims2.1X;