- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Графика DirectX в Delphi - Михаил Краснов
Шрифт:
Интервал:
Закладка:
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
X, Y, Z : Single;
normVector : TD3DVector;
Color : DWORD;
end;
TCUSTOMVERTEXEagle = packed record
X, Y, Z :
Single;
normVector : TD3DVector;
end;
const
D3DFVF_CUSTOMVERTEXLand = D3DFVF_XYZ or D3DFVF_NORMAL or
D3DFVFJJIFFUSE; D3DFVF CUSTOMVERTEXEagle = D3DFVF_XYZ or D3DFVF_NORMAL;
При воспроизведении переключаем потоки источников, задавая в качестве таковых буферы, содержащие вершины различных форматов. При подобном подходе существенно экономится память.
Особое внимание мы должны обратить на то, как в этом примере заполняется буфер вершин модели. Рекомендованная мною импортирующая программа в качестве одного из форматов позволяет использовать код на языке C++. Для подготовки этого примера я результирующий файл преобразовал в код на языке Pascal. Это совершенно не сложно, поскольку большая его часть представляет собой массивы данных. Только имя массива, содержащего данные вершин, пришлось изменить на Avertices, чтобы не появилось конфликтов с переменной Vertices.
Первые 13 строк такого файла необходимо удалить. Также удаляются последние строки кода, начиная со строки GLint GenSoobjectListо. В оставшемся файле убираются все символы f, предшествующие запятой и фигурной скобке. Далее все фигурные скобки заменяются на обычные.
Последнее, что необходимо сделать - изменить синтаксис описания массиюв. Например, такая строка
tatic GLint face_indicies[1200][9]
заменяется следующей:
ace_indicies : array [0..1199, 0..8] of integer
Тип GLfloat заменяется типом single, остальные типы соответствуют целому.
Толученный файл с директивой include подключается к головному модулю роекта (в секцию const), а код функции инициализации буфера становится рактически универсальным, в зависимости от модели меняется только чисо, задающее размер буфера. Впрочем, и это число можно заменить выражением, опирающемся на размер массива normals. Также, возможно, потре-уется исправить и масштабный множитель:
unction TfrmD3D.InitVBEagle : HRESULT;
var
Vertices : ~TCustomVertexEagle;
hRet : HRESULT;
i, j : Integer;
vi : Integer; // Индекс вершин треугольников
ni : Integer; // Индекс нормалей треугольников
begin
hRet := FDSDDevice.CreateVertexBuffer(10500 *
SizeOf(TCustomVertexEagle), 0, D3DFVF_CUSTOMVERTEXEagle, D3DPOOL_DEFAULT, FD3DVBEagle);
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
hRet := FD3DVBEagle.Lock(0, 10500 * SizeOf(TCustomVertexEagle),
PByte(Vertices), 0) ;
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Цикл заполнения буфера данными из массивов
for i := 0 to sizeof(face_indicies) div sizeof(face__indicies[0]) - 1 do for j := 0 to 2 do begin
vi := face_indicies[i][j]; // Индекс фасета
ni := face_indicies[i] [j+3]; // Индекс нормали фасета
// Исходные данные масштабируем, умножая на 5
Vertices.X := Avertices[vi][0] * 5;
Vertices.Y := Avertices[vi][1] * 5;
Vertices.Z := Avertices[vi][2] * 5;
Vertices.normVector.X := normals[ni] [0] ;
Vertices.normVector.Y := normals[ni][1];
Vertices.normVector.Z := normals[ni][2];
Inc(Vertices);
end;
Result := FDSDVBEagle.Unlock;
end;
При инициализации работы один раз устанавливается материал, а при воспроизведении необходимо указывать, окрашивание производится исходя из цветовой составляющей вершины, либо используется установленный материал:
with FDSDDevice do begin
SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
// Для ландшафта цвет примитивов задается цветовой составляющей вершин
SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
SetTransform(D3DTS_WORLD, IdentityMatrix); // Выключаем третий источник,
// предназначенный для освещения только модели
LightEnable(2, False);
SetStreamSource(0, FD3DVBLand, SizeOf(TCustomVertexLand));
SetVertexShader(D3DFVF_CUSTOMVERTEXLand);

