Краснов Михаил
Шрифт:
Матрицы, связанные с поворотом конечностей, из соображений оптимизации вычисляются не при каждой перерисовке кадра, а только при изменении значений управляющих переменных. Обратите внимание, что поворот конечностей в точках крепления осуществляется следующим образом: система координат перемещается в точку крепления, выполняется поворот, а затем система координат возвращается в первоначальное положение:
procedure TfrmDSD.MoveMan;
begin
// Поворот глобальной системы координат,
// вращение всей модели вокруг своей оси
SetRotateZMatrix (matRot, Angle);
// Переменная, задающая вращение конечностей
AngleFoot := AngleFoot + StepFoot;
if (AngleFoot > Pi / 4) or (AngleFoot < -Pi / 4}
then StepFoot := -StepFoot; // Ноги вращаются в противофазе
SetRotateXMatrix (rotLeftFoot, AngleFoot);
SetRotateXMatrix (rotRightFoot, -AngleFoot); // Поворот левой ноги, в три этапа
matLeftFoot := MatrixMul(matRot,
MatrixMul(transFoot2, MatrixMul(rotLeftFoot, transFootl))); // Поворот правой ноги
matRightFoot := MatrixMul(matRot,
MatrixMul(transFoot2,
MatrixMul(rotRightFoot, transFootl))); // Поворот левой руки
matLeftHand := MatrixMul(matRot,
MatrixMul(transHand2,
MatrixMul(rotRightFoot, transHandl))); // Поворот правой руки
matRightHand := MatrixMul(matRot,
MatrixMul(transHand2, MatrixMul(rotLeftFoot, transHandl)));
end;
Рабочие матрицы, связанные с перемещениями в точки крепления конечностей, инициализируются один раз, в начале работы приложения:
SetTranslateMatrix(transFootl, О, О, 0.25);
SetTranslateMatrix(transFoot2, О, О, -0.25);
SetTranslateMatrix(transHandl, 0.25, 0.0, -0.23);
SetTranslateMatrix(transHand2, -0.25, 0.0, 0.23);
Этот пример я подготовил для использования в дальнейшем в расчете на то, что человечком можно будет легко управлять, перемещая его в пространстве. Но если на сцене присутствует только одна модель, для оптимизации можно сократить количество операций с матрицами. В самом деле, в этом примере матрица matRot, связанная с глобальной системой координат, может вообще не использоваться: модель можно не вращать и оставить неподвижной, а перемещать точку зрения наблюдателя. Эффект вращения модели останется, а количество операций существенно уменьшится.
И теперь мы можем перейти к разбору заключительного примера - проекта каталога Ех21. Как я уже говорил, это заготовка трехмерной игры: игрок попадает внутрь комнаты, населенной движущимися человечками .
Окружение игрока построено из текстур, накладываемых на треугольники, описание окружающего мира загружается из текстового файла.DirectX.
type
// Формат вершин для треугольников окружения
TNormDiffTextVertex = packed record
X, Y, Z : Single;
nX, nY, nZ : Single;
DColor : DWORD;
U, V : Single;
end;
// Формат вершин для треугольников человечков
TNormVertex = packed record
X, Y, Z : Single;
nX, nY, nZ : Single;
end;
// Отдельный треугольник описания окружения
TTriangle '= record
NumTexture : Integer; // Номер текстуры
DIFFUSE : DWORD; // Диффузная составляющая треугольника
end;
const
// FVF-флаг для треугольников окружения
D3DFVF_NORMDIFFTEXTVERTEX = D3DFVF_XYZ or D3DFVF_NORMAL or
D3DFVF_DIFFUSE or D3DFVFJTEX1; // FVF-флаг для треугольников человечков
D3DFVFJSIORMVERTEX = D3DFVF_XYZ or D3DFVFJTORMAL;
// Имя файла с описанием мира
WorldFile = 'Data/World.txt';
// Имя файла с треугольниками символов, для вывода FPS
NumbersFile = 'Data/Numbers.txt';
// Количество треугольников в описании окружения
NumTriangles = 58;
($1 legoman.pas) // Данные модели
var
frmD3D: TfrmD3D;
Frames : Integer =0; // Счетчик кадров
FpsOut : String = ''; // Значение FPS
// Вспомогательная матрица, для вывода символов FPS
LetTrans : TDSDMatrix;
// Используется как вспомогательный массив для хранения образа текстуры
TexPointer : Pointer;
// Характеристики образа текстуры
wrkTexWidth, wrkTexHeight :
Integer;
// Флаг, выводить ли FPS
flgFPS : BOOL = True;
// Угол зрения по вертикали