Михаил Краснов - Графика DirectX в Delphi
- Название:Графика DirectX в Delphi
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Михаил Краснов - Графика DirectX в Delphi краткое содержание
Графика DirectX в Delphi - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
matWrk := MatrixMul(matWrk, MatrixMul(matTranslate, matRotateX));
with FD3DDevice do begin
SetTransform(D3DTS_WORLD, matWrk);
DrawPrimitive(D3DPT_TRLANGLESTRIP, 60, 98);
end;
// Туловище
// Цилиндр с левой стороны туловища
SetTranslateMatrix(matTranslate, -0.2, 0.0, 0.0);
SetRotateZMatrix(matRotateZ, 5 * Pi / 6) ;
with FD3DDevice do begin
SetTransform(D3DTS_WORLD, MatrixMul(matTranslate, matRotateZ));
SetMaterial(MaterialGreen); // Текущий цвет - зеленый
DrawPrimitive(D3DPT_TRJANGLESTRIP, 60, 98);
end;
// Цилиндр правой части туловища
SetTranslateMatrix(matTranslate, 0.2, 0.0, 0.0);
SetRotateZMatrix(matRotateZ, -5 * Pi / 6);
FD3DDevice.SetTransform(D3DTS_WORLD,
MatrixMul(matTranslate, matRotateZ));
FD3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 60, 98);
// Цилиндр верхней части туловища
SetTranslateMatrix(matTranslate, -1.0, -1.0, 0.0);
SetScaleMatrix (matScale, 1.0, 2.0, 1.0); // Растягиваем цилиндр
SetRotateZMatrix(matRotateZ, Pi / 2);
FD3DDevice.SetTransform(D3DTS_WORLD, MatrixMul(matRotateZ,
MatrixMul(matTranslate, matScale)));
FD3DDevice.DrawPrimitive(D3DPT TRIANGLESTRIP, 60, 98);
// Цилиндр нижней части туловища
SetTranslateMatrix(matTranslate, 0.0, -0.25, 0.0);
SetScaleMatrix (matScale, 1.0, 0.5, 1.0); // Уменьшаем цилиндр
SetRotateZMatrix(matRotateZ, Pi / 2) ;
FD3DDevice.SetTransform(D3DTS_WORLD, MatrixMul(matRotateZ,
MatrixMul(matTranslate, matScale)));
FD3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 60, 98);
// Левая рука
// Верхняя часть
SetTranslateMatrix(matTranslate, -1.0, -1.0, 0.0);
SetRotateZMatrix(matRotateZ, R_hand_up_angle);
matWrk := MatrixMul(matTranslate, matRotateZ);
with FD3DDevice do begin
SetTransform(D3DTS_WORLD, matWrk);
SetMaterial(MaterialRed); // Текущий цвет - красный
// Цилиндр длиной 0.75
DrawPrimitive(D3DPT_TRIANGLESTRIP, 160, 98);
end;
// Сдвигаемся к концу цилиндра
SetTranslateMatrix(matTranslate, 0.0, 0.75, 0.0);
SetRotateZMatrix(matRotateZ, R_hand_down_angle);
matWrk := MatrixMul(matWrk, MatrixMul(matTranslate, matRotateZ));
with FD3DDevice do begin
SetTransform(D3DTS_WORLD, matWrk);
DrawPrimitive(D3DPT_TRIANGLESTRIP, 160, 98);
end;
// Правая рука
SetTranslateMatrix(matTranslate, 1.0, -1.0, 0.0);
SetRotateZMatrix(matRotateZ, L_hand_up_angle);
matWrk := MatrixMul(matTranslate, matRotateZ);
with FD3DDevice do begin
SetTransform(D3DTS_WORLD, matWrk);
DrawPrimitive(D3DPT_TRIANGLESTRIP, 160, 98);
end;
SetTranslateMatrix(matTranslate, 0.0, 0.75, 0.0);
SetRotateZMatrix(matRotateZ, L_hand_down_angle);
matWrk := MatrixMul(matWrk, MatrixMul{matTranslate, matRotateZ));
with FDSDDevice do begin
SetTransform(D3DTS_WORLD, matWrk);
DrawPrimitive(D3DPT_TRIANGLESTRIP, 160, 98);
end;
end;
При нажатии клавиш управления курсором меняются значения флагов, и наблюдаем мы сцену зеркально.
procedure TfrmD3D.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VKJ3SCAPE then Close else
// Клавиша "влево" - правая рука
if Key = VK_LEFT then R_hand_move := not R_hand_move else
// Клавиша "вправо" - левая рука
if Key = VK_RIGHT then L_hand_move := not L_hand_move else
// Клавиша "вверх" - правая нога
if Key = VK_UP then begin
// Двигается, если не поднята левая нога
if L_foot_up_angle < 1.0 then R_foot_move := not R_foot_move;
end else
// Клавиша "вниз" - левая нога
if Key = VK_DOWN then begin
// Двигается, если не поднята правая нога
if R_foot_up_angle < 1.0 then L_foot_move := not L_foot_move;
end;
end;
При установленных флагах значения углов поворотов увеличиваются на величину INCR:
procedure TfrmDSD.Timer;
begin
if R_hand_move then begin // Правая рука поднимается
if R_hand_up_angle < Pi / 2 then begin // He достигнут предел
R_hand_up_angle := R_hand_up_angle + INCR; // Верхняя часть руки
R_hand_down_angle := R_hand_down_angle - INCR; // Нижняя часть
end // Предел достигнут, движется только нижняя часть руки
else if (R_hand_up_angle >= Pi / 2) and (R_hand_down_angle < 0.0)
then R_hand_down_angle := R_hand_down_angle + INCR;
end else // Правая рука опускается или уже опущена
if R_hand_up_angle > 0.0 then begin
R_hand_up_angle := R_hand_up_angle - INCR; if R_hand_down_angle < 0.0
then R_hand_down_angle := R_hand_down_angle + INCR;
end;
if L_hand_move then begin // Левая рука поднимается
if L_hand_up_angle > -Pi / 2 then begin
L_hand_up_angle := L_hand_up_angle - INCR;
L_hand_down_angle := L__hand_down_angle + INCR;
end else if (L_hand_up_angle <= Pi / 2) and (L_hand_down_angle > 0.0)
then L_hand_down_angle := L_hand_down_angle - INCR;
end else if L__hand__up_angle < 0.0 then begin
L_hand_up_angle := L_hand_up_angle + INCR;
if L_hand_down_angle > 0.0
then L_hand_down_angle := L_hand_down_angle - INCR;
end;
if R_foot_move then begin // Правая нога поднимается
if R_foot_up_angle < Pi / 2 then begin
R_foot_up_angle := R_foot__up_angle + INCR;
R_foot_down_angle := R_foot_down_angle - INCR;
end else if (R_foot_up_angle >= Pi / 2) and (R_foot_down_angle < 0.0)
then R_foot_down_angle := R_foot_down_angle + INCR;
end else if R_foot_up_angle > 0.0 then begin
R_foot_up_angle := R_foot_up_angle - INCR; if R_foot_down_angle < 0.0
then R_foot_down_angle := R_foot_down_angle + INCR;
end;
if L_foot_move then begin // Движение левой ноги
if L_foot_up_angle < Pi / 2 then begin
L_foot_up_angle := L_foot_up_angle + INCR;
L_foot_down_angle := L_foot_down_angle - INCR;
end else
if (L_foot_up_angle >= Pi / 2) and (L_foot_down_angle < 0.0)
then L_foot_down_angle := L_foot_down_angle + INCR;
end else
if L_foot_up_angle > 0.0 then begin
L_foot_up_angle := L_foot_up_angle - INCR;
if L_foot_down_angle < 0.0
then L_foot_down_angle := L_foot_down_angle + INCR;
end;
end;
Из этого примера мы также можем вынести для себя механизм удобной навигации в пространстве. Матрица проекций задается один раз, при инициализации:
procedure TfrmD3D.FormCreate(Sender: TObject);
var
hRet : HRESULT;
matView, matProj : TDSDMatrix;
begin
hRet := InitD3D;
if Failed (hRet) then ErrorOut ('InitDSD', hRet);
hRet := InitVB;
if Failed (hRet) then ErrorOut ('InitVertex', hRet);
SetupLights;
MaterialRed := InitMaterial(1, 0, 0, 1);
MaterialBlue := InitMaterial(0, О, 1,1);
MaterialGreen := InitMaterial(О, 1, 0, 1) ;
MaterialYellow := InitMaterial(1, 1, 0, 1) ;
// Первоначальная установка видовой матрицы
SetViewMatrix(matView, D3DVector(2, 1, 5),
D3DVector(0, 0, 0), D3DVector(0, -1, 0));
FD3DDevice.SetTransform(D3DTS_VIEW, matView);
// Матрица проекций задается один раз
SetProjectionMatrix(matProj, 1, 1, 1, 20);
FD3DDevice.SetTransform(D3DTS_PROJECTION, matProj);
end;
Положение точки зрения и параметры матриц я подобрал с помощью пройденного нами примера с осями координат.
При движении курсора мыши с нажатой кнопкой видовая матрица пересчитывается в соответствии с положением курсора:
procedure TfrmDSD.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Down := True; // Кнопка нажата, флаг устанавливается
оХ := X; // Запомнили положение курсора
oY := Y;
end;
procedure TfrmD3D.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift:. TShiftState; X, Y: Integer);
begin
Down : = False; // Кнопка отпущена, флаг сбрасывается
end;
procedure TfrmDSD.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
eyeX, eyeZ : Single; matView : TD3DMatrix;
begin
if Down then begin // При нажатой кнопке мыши
// Величина перемещения курсора по горизонтали
// задает перемещения точки обзора в пространстве по осям X и Z
Angle := Angle + (X - оХ) / 50.0;
// Перемещение курсора по вертикали задает сдвиг по оси Y
sHeight := sHeight + (У - oY) / 15.0;
eyeX := cos(Angle) * 5;
eyeZ := sin(Angle) * 5;
// Устанавливаем новую видовую матрицу
SetViewMatrixfmatView, D3DVector(eyeX, sHeight, eyeZ),
D3DVector(0, 0, 0), D3DVector(0, -I, 0));
FD3DDevice.SetTransform(D3DTS VIEW, matView);
// Запомнили новое положение курсора
оХ := X;
oY := Y;
end;
end;
В качестве упражнения "обуйте" человечка в башмаки, для чего постройте параллелепипед, масштабируя куб.
Итак, с помощью цилиндров и кубиков мы можем получить занятные построения, но наверняка трудно удовлетвориться только такими фигурами. Вы уже видели в одном из предыдущих примеров модель чайника и справедливо полагаете, что она создана с использованием редактора, а опорные точки треугольников извлечены мною с помощью каких-то дополнительных средств. Конечно, для масштабных проектов требуются подобные вспомогательные средства, облегчающие процесс разработки будущих элементов сцены. Большинство трехмерных редакторов и программ моделирования объектов позволяют записывать в открытом формате или применять собственные форматы с помощью встраиваемых модулей. Так, к примеру, вы можете использовать распространенный DXF-формат, поддерживаемый большинством трехмерных редакторов, а из файла такого формата легко извлекаются вершины треугольников, образующих модель. В каталоге Ех06 располагается проект, с помощью которого я получил из файла такого формата текстовый файл, содержащий данные о нормалях и треугольниках модели чайника. При запуске приложения запрашиваются имена DXF-файла и файла-результата.
Читать дальшеИнтервал:
Закладка: