wrkVector.X := - nx / wrki;
wrkVector.Y := - ny / wrki;
wrkVector.Z := - nz / wrki;
Мне пришлось столкнуться с тем, что многие корреспонденты обращаются с возникающими проблемами при обработке DXF-файлов, поэтому должен четко ограничить круг действительно серьезных проблем лишь двумя: либо файл не содержит разбиение модели по треугольникам, либо вершины треугольников перечисляются в различном порядке. Во всех остальных случаях решение получить нетрудно.
Достоинствами использования DXF-файлов является то, что это открытый формат, и поддерживается он практически всеми моделирующими программами. Недостатки таковы:
* модель строится по отдельным, независимым треугольникам, что приводит к избыточности данных; это текстовый формат, поэтому для больших моделей получаются файлы гигантских размеров.
Однако в наших примерах эти файлы нужны только при подготовке кода, непосредственно при работе приложения они не применяются, и нет необходимости распространять их вместе с приложением. Наши примеры загружают данные модели из текстового файла. Полученные текстовые файлы, конечно, тоже имеют большие размеры, но помните, что вы не обязаны использовать именно текстовые файлы. Записывайте данные в виде вещественных значений, и объем файла сразу же значительно уменьшится.
А теперь перейдем к следующему примеру, проекту каталога Ех07 - несложной заготовке увлекательной игры. Вам остается только развить программу, чтобы получить законченное произведение, со стрельбой и коварными противниками, а пока что сюжет игры совсем прост: космический корабль мчится в пространстве, наполненном сферами (рис. 9.8).
Уже сейчас пример во многом напоминает профессиональный продукт: существует полноэкранный режим. Для управления положением космического корабля используется библиотека Directlnput.
Модели сферы и космического корабля загружаются из текстовых файлов, их я получил с помощью изученных утилит.
Поскольку операции с матрицами осуществляются центральным процессором, а именно нашим приложением, оптимизации их выполнения необходимо уделять максимум внимания. Для каждой движущейся сферы запоминаем текущую матрицу трансформаций, чтобы не тратить время на ее инициализацию при очередном обновлении кадра:
type
TSPHERE = packed record // Запись, относящаяся к отдельной сфере
Z : Single; // Текущая координата по оси Z
Radius : Single; // Радиус
MaterialSphere : TD3DMaterial8; // Индивидуальный материал
matSphere : TDSDMatrix; // Текущая матрица трансформаций сферы
end;
const
NumSpheres = 60; // Количество сфер
var
Spheres : Array [0..NumSpheres - 1] of TSPHERE; // Массив сфер
MaterialXWing : TD3DMaterial8; // Материал космического корабля
matXWing : TD3DMatrix; // Матрица трансформаций корабля
Заполняются целиком матрицы трансформаций сфер и корабля один раз, при инициализации:
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);
// Модель корабля нарисована по часовой стрелке
Читать дальше
Конец ознакомительного отрывка
Купить книгу