- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Графика DirectX в Delphi - Михаил Краснов
Шрифт:
Интервал:
Закладка:
Буфер вершин заполняется данными для трех трехмерных объектов: цилиндра, конуса и чайника:
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. О том, как получены точки модели, мы поговорим чуть позже, сейчас же я должен сообщить, что вершины треугольников модели перечисляются против часовой стрелки.
Текущие параметры матриц вида и проекций хранятся в следующих переменных:
FromX, FromY, FromZ : Single;
AtX, AtY, AtZ : Single;
WorldUpX, WorldUpY, WorldUpZ : Single;
fFOV, fAspect, fNearPlane, fFarPlane : Single;
Инициализируются эти переменные значениями, такими же, как в предыдущих примерах, лишь точка зрения отодвинута на единицу:
procedure TfrmDSD.FormCreate(Sender: TObject);
var
hRet : HRESULT;
begin
hRet := InitD3D;
if Failed (hRet) then ErrorOut (4nitD3D'f hRet);
hRet := InitVB;
if Failed (hRet) then ErrorOut ('InitVertex', hRet);
// Включаем источники света и инициализируем материалы
SetupLights;
MaterialRed := InitMaterial(1, 0, 0, 1);
MaterialBlue := InitMaterial(0, 0,1, 1);
MaterialGreen := InitMaterial(0, 1, 0, 1) ;
MaterialYellow := InitMaterial(1, 1, 0, 1);
FromX := 0.0; // Вектор "From"
FromY := 0.0;
FromZ := -6.0;
AtX := 0.0; // Вектор "At"
AtY := 0.0;
AtZ := 0.0;
WorldUpX := 0.0; // Вектор "WorldUp"
WorldUpY := 1.0;
WorldUpZ := 0.0;
fFOV := 1.0; // Угол обзора по оси Y
fAspect := 1.0; // Угол обзора по оси X
fNearPlane := 1.0; // Передняя плоскость отсечения
fFarPlane := 20; // Задняя плоскость отсечения
end;
Для повышения красочности на сцене присутствует два источника света:
procedure TfrmDSD.SetupLights;
var
LightO : TD3DLight8;
Lightl : TD3DLight8;
begin
LightO := InitDirectionalLight(D3DVector(-1, -1, -1), 1, 1, 1, 0);
FDSDDevice.SetLight (0, LightO);
Lightl := InitDirectionalLight(D3DVector(0, 0, 1), 1, 1, 1, 0);
FDSDDevice.SetLight (1, Lightl);
FD3DDevice.LightEnable (0, True);
FD3DDevice.LightEnable (1, True);
end;
При воспроизведении объектов сцены параметры матриц вида и проекций опираются на текущие значения управляющих переменных:
procedure TfrmDSD.DrawScene;
var
matView, matProj : TD3DMatrix;
matRotate, matTranslate : TDSDMatrix;
matRotateX, matRotateY : TD3DMatrix;
matScale : TD3DMatrix;
begin
// Цилиндр по оси X
SetRotateZMatrix(matRotate, Pi / 2);
SetTranslateMatrix(matTranslate, 1.0, 0.0, 0.0);
with FD3DDevice do begin
SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
SetTransform(D3DTS_WORLD, MatrixMul(matTranslate, matRotate));
SetMaterial(MaterialRed); // Красного цвета
DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 50 * 2 - 2);
end;
// Конус стрелки по оси Z
SetRotateYMatrix(matRotate, Pi / 2);
SetTranslateMatrix(matTranslate, 2.0, 0.0, 0.0);
SetScaleMatrix(matScale, 1.0, 0.5, 0.5);
with FDSDDevice do begin
SetTransform(D3DTS_WORLD, MatrixMul(matScale,
MatrixMul(matTranslate, matRotate)));
DrawPrimitive(D3DPT_TRIANGLEFAN, 100, 49); // Сам конус
DrawPrimitive(D3DPT_TRIANGLEFAN, 151, 50); // Донышко конуса
end;
// Цилиндр по оси Y
SetTranslateMatrix(matTranslate, 0.0, 1.0, 0.0);
with FDSDDevice do begin
SetTransform(D3DTS__WORLD, matTranslate);
SetMaterial(MaterialGreen); // Цвет - зеленый
DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 50 * 2 - 2);
end;
// Конус стрелки по оси Y SetRotateXMatrix(matRotate, -Pi / 2);
SetTranslateMatrix(matTranslate, 0.0, 2.0, 0.0);
SetScaleMatrix(matScale, 0.5, 1.0, 0.5);
with FD3DDevice do begin
SetTransform(D3DTS_WORLD, MatrixMul(matScale,
MatrixMul(matTranslate, matRotate)));
DrawPrimitive(D3DPT_TRIANGLEFAN, 100, 49);
DrawPrimitive(D3DPT_TRIANGLEFAN, 151, 50);
end;
// Цилиндр по оси Z
SetRotateXMatrix(matRotate, Pi / 2) ;
SetTranslateMatrix(matTranslate, 0.0, 0.0, 1.0);
with FD3DDevice do begin
SetTransform(D3DTS_WORLD, MatrixMul(matTranslate, matRotate));
SetMaterial(MaterialBlue); // Синего цвета
DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 50 * 2 - 2);
end;
// Конус стрелки по оси Z
SetTranslateMatrix(matTranslate, 0.0, 0.0, 2.0);
SetScaleMatrix(matScale, 0.5, 0.5, 1.0); with FD3DDevice do begin
SetTransform(D3DTS_WORLD, MatrixMul(matScale, matTranslate));
DrawPrimitive(D3DPT_TRIANGLEFAN, 100, 49);
DrawPrimitive(D3DPT_TRIANGLEFAN, 151, 50);
end;
// Чайник, вращающийся вокруг осей X и Y
SetRotateXMatrix(matRotateX, Angle);
SetRotateYMatrixfmatRotateY, Angle);
SetTranslateMatrix(matTranslate, 0.0, -1.5, 0.0);
SetScaleMatrix(matScale, 0.5, 0.5, 0.5); // Уменьшаем в два раза
with FD3DDevice do begin
SetTransform(D3DTS_WORLD, MatrixMul(matRotateX, MatrixMul(matRotateY, MatrixMul(matScale, matTranslate))));
SetMaterial(MaterialYellow);
// Вершины модели перечисляются против часовой стрелки
SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
DrawPrimitive(D3DPT_TRIANGLELIST, 100 + 51 * 2, 6322);
end;
// Матрица вида
SetViewMatrix(matView, DSDVector(FromX, FromY, FromZ),
D3DVector(AtX, AtY, AtZ), DSDVector(WorldUpX, WorldUpY, WorldUpZ));
FD3DDevice.SetTransform(D3DTS_VIEW, matView); // Матрица проекций
SetProjectionMatrix(matProj, fFOV, fAspect, fNearPlane, fFarPlane);
FD3DDevice.SetTransform(D3DTS_PROJECTION, matProj);
end;
Поначалу, наверняка, вам будет тяжело разбирать последовательности манипуляций с матрицами при воспроизведении нескольких объектов. Для приобретения опыта попробуйте решить простейшие задачи, например удлините цилиндры и конусы осей.
Но главное предназначение этого примера - разрешить все возможные вопросы об установках матриц вида и проекций. По нажатии клавиши <Пробел> появляется вспомогательное окно, в полях редактирования которого выводится текущее значение управляющих переменных:
procedure TfrmDSD.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VKJESCAPE then Close else
if Key = VK_SPACE then with Form2 do begin
edtFromX.Text := FloatToStr (FromX);
edtFromY.Text := FloatToStr (FromY);
edtFromZ.Text := FloatToStr (FromZ);
edtAtX.Text := FloatToStr (AtX);
edtAtY.Text := FloatToStr (AtY) ;
edtAtZ.Text := FloatToStr (AtZ);
edtWorldUpX.Text := FloatToStr (WorldUpX);
edtWorldUpY.Text := FloatToStr (WorldUpY);
edtWorldUpZ.Text := FloatToStr (WorldUpZ);
edtFOV.Text := FloatToStr (fFOV);
edtAspect.Text := FloatToStr (fAspect);
edtNearPlane.Text := FloatToStr (fNearPlane);
edtFarPlane.Text := FloatToStr (fFarPlane);
Show;
end;
end;
Первоначально мы видим только две оси: стрелка оси Z закрыта вращающейся моделью. Меняя значения координат вектора "From", мы передвигаем точку обзора - координаты той точки в пространстве, где находится глаз наблюдателя. Вектор "At" определяет точку, находящуюся в середине сцены. Если здесь задавать отличные друг от друга значения, то наша композиция будет перемещаться по плоскости экрана, т. е. этот вектор соответствует направлению взгляда наблюдателя. Вектор "WorldUp" указывает направление и величину поворота головы. Если менять значения его составляющих, оси нашей сцены начнут "меняться местами".
Значение FOV задает величину производимого увеличения в радианах. Чем меньше это число, тем крупнее выглядит наша картинка. Обратите внимание, что сами объекты при этом не перемещаются, мы как будто просто вращаем колесико настройки бинокля. Значение величины Aspect определяет степень сжатия картинки по горизонтали: чем больше это число, тем сильнее растягивается изображение. Обычно здесь передается отношение ширины окна к его высоте.
Расстояния до передней и задней плоскостей отсечения задают видимую область пространства. Расстояния отмеряются от глаза наблюдателя. Все точки, выходящие за пределы этой области, не воспроизводятся. Из соображений оптимизации плоскости сечения располагаются максимально близко друг к другу, чтобы сократить время вычислений. Обратите внимание, это очень важно: нельзя устанавливать нулевым значение расстояния до передней плоскости отсечения. Такое значение равносильно отказу от использования буфера глубины.

