Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Жарков В.А. - Visual C++ 2005, DirectX 9.0c и Microsoft Agent в компьютерной графике, мультимедиа и играх (Листинги книги) - 2005

.pdf
Скачиваний:
306
Добавлен:
13.08.2013
Размер:
1.14 Mб
Скачать

70 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005

DesigningLine(D, H, -B, C, H, -A);

DesigningLine(C, H, -A, R, H, 0);

DesigningLine(R, H, 0, 0, 1, 0);

DesigningLine(C, H, A, 0, 1, 0);

DesigningLine(D, H, B, 0, 1, 0);

DesigningLine(D, H, -B, 0, 1, 0);

DesigningLine(C, H, -A, 0, 1, 0); DesigningLine(-R, -H, 0, -C, -H, A); DesigningLine(-C, -H, A, -D, -H, B); DesigningLine(-D, -H, B, -D, -H, -B); DesigningLine(-D, -H, -B, -C, -H, -A); DesigningLine(-C, -H, -A, -R, -H, 0); DesigningLine(-R, -H, 0, 0, -1, 0); DesigningLine(-C, -H, A, 0, -1, 0); DesigningLine(-D, -H, B, 0, -1, 0); DesigningLine(-D, -H, -B, 0, -1, 0); DesigningLine(-C, -H, -A, 0, -1, 0); DesigningLine(R, H, 0, -D, -H, B); DesigningLine(R, H, 0, -D, -H, -B); DesigningLine(C, H, A, -D, -H, B); DesigningLine(C, H, A, -C, -H, A); DesigningLine(D, H, B, -C, -H, A); DesigningLine(D, H, B, -R, -H, 0); DesigningLine(D, H, -B, -R, -H, 0); DesigningLine(D, H, -B, -C, -H, -A); DesigningLine(C, H, -A, -C, -H, -A); DesigningLine(C, H, -A, -D, -H, -B); Icosahedron_last = NumLines;

}

//Объявляем структуру Line и массивы этой структуры: public: value struct Line

{

//Объявляем массивы для соединения точек (points): public: array<float>^ fr_points;

public: array<float>^ to_points;

//Массивы для соединения преобразованных точек: //(transformed (tr) points):

public: array<float>^ fr_tr_points; public: array<float>^ to_tr_points; //Создаем и инициализируем массивы, т.е.

//всем элементам каждого массива присваиваем 0: public: void Initialize()

{

fr_points = gcnew array<float>(5); to_points = gcnew array<float>(5); fr_tr_points = gcnew array<float>(5); to_tr_points = gcnew array<float>(5);

Глава 24. Изображение и управление трехмерными объектами

71

}

};

//Объявляем массив Lines структуры Line, оператором gcnew //создаем массив из 100 элементов и инициализируем его, //т.е всем элементам массива присваиваем значение nullptr: public: static array<Line>^ Lines = gcnew array<Line>(100);

//Объявляем и инициализируем переменную для индекса массива: public: int static NumLines = 0;

//Проектируем линию между точками (x1,y1,z1),(x2,y2,z2): public: void DesigningLine(float x1, float y1, float z1, float x2, float y2, float z2)

{

NumLines = NumLines + 1; //Инициализируем и рассчитываем массив: Lines[NumLines].Initialize(); Lines[NumLines].fr_points[1] = x1; Lines[NumLines].fr_points[2] = y1; Lines[NumLines].fr_points[3] = z1; Lines[NumLines].fr_points[4] = 1; Lines[NumLines].to_points[1] = x2; Lines[NumLines].to_points[2] = y2; Lines[NumLines].to_points[3] = z2; Lines[NumLines].to_points[4] = 1;

}

//Применяем матрицу переноса (translation matrix) //ко всем линиям, используя MatrixApplyFull.

//Преобразование не имеет 0, 0, 0, 1 в последнем столбце: public: void TransformAllDataFull(array<float,2>^ M)

{

TransformDataFull( M, 1, NumLines);

}

//Применяем матрицу переноса (translation matrix)

//ко всем выделенным линиям, используя MatrixApplyFull. //Преобразование не имеет 0, 0, 0, 1 в последнем столбце: public: void TransformDataFull(array<float,2>^ M,

int line1, int line2)

{

for (int i = line1; i <= line2; i++)

{

MatrixApplyFull( Lines[i].fr_points, M, Lines[i].fr_tr_points);

MatrixApplyFull( Lines[i].to_points, M, Lines[i].to_tr_points);

}

}

72 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005

//Рисуем выделенные преобразованные линии: public: void DrawSolid(Bitmap^ bmp,

int first_line, int last_line, Color color, bool clear)

{

float x1, y1, x2, y2; Graphics^ g; Pen^ pen;

//Задаем толщину линии рисования, например, 2 //(цвет линии мы задали в методе Designing): pen = gcnew Pen(color, 2);

//Связываем объект g с изображением bmp: g = Graphics::FromImage(bmp);

if (clear) g->Clear(System::Drawing::Color::Black); //Рисуем линии:

for (int i = first_line; i <= last_line; i++)

{

x1 = Lines[i].fr_tr_points[1];

y1 = Lines[i].fr_tr_points[2];

x2 = Lines[i].to_tr_points[1];

y2 = Lines[i].to_tr_points[2];

//Масштабируем, нормализуем и рисуем многогранник: g->DrawLine(pen,

(x1 * bmp->Width / 4) + bmp->Width / 2.0F, bmp->Height / 2.0F - (y1 * bmp->Height / 4), (x2 * bmp->Width / 4) + bmp->Width / 2.0F, bmp->Height / 2.0F - (y2 * bmp->Height / 4));

}

//Высвобождаем ресурсы от объектов g и pen: g->Dispose(); pen->Dispose();

}

//Строим единичную матрицу:

public: void MatrixIdentity(array<float,2>^ M)

{

for (int i = 1; i <= 4; i++)

{

for (int j = 1; j <= 4; j++)

{

if (i == j) M[i, j] = 1; else M[i, j] = 0;

}

}

}

//Строим матрицу преобразования (3-D transformation matrix) //для перспективной проекции вдоль оси z на плоскость x,y //с центром объекта (фокусом) в начале координат

//и c центром проецирования на расстоянии (0, 0, Distance): public: void MatrixPerspectiveXZ(array<float,2>^ M,

float Distance)

Глава 24. Изображение и управление трехмерными объектами

73

{

MatrixIdentity(M);

if (Distance != 0) M[3, 4] = -1 / Distance;

}

//Строим матрицу преобразования (3-D transformation matrix) //для проецирования с координатами:

//центр проецирования (cx, cy, cz), фокус (fx, fy, fx), //вектор от объекта до экрана UP <ux, yx, uz>,

//тип проецирования (type_of_projection): //PerspectiveProjection или ParallelProjection: public: void MatrixTransformation(array<float,2>^ M, int type_of_projection,

float Cx, float Cy, float Cz, float Fx, float Fy, float Fz, float ux, float uy, float uz)

{

array<float,2>^ M1 = gcnew array<float,2>(5, 5); array<float,2>^ M2 = gcnew array<float,2>(5, 5); array<float,2>^ M3 = gcnew array<float,2>(5, 5); array<float,2>^ M4 = gcnew array<float,2>(5, 5); array<float,2>^ M5 = gcnew array<float,2>(5, 5); array<float,2>^ M12 = gcnew array<float,2>(5, 5); array<float,2>^ M34 = gcnew array<float,2>(5, 5); array<float,2>^ M1234 = gcnew array<float,2>(5, 5); float sin1 = 0, cos1 = 0; float sin2 = 0, cos2 = 0; float sin3, cos3; float A, B, C; float d1, d2, d3; array<float>^ up1 = gcnew array<float>(5); array<float>^ up2 = gcnew array<float>(5); //Переносим фокус (центр объекта) в начало координат: MatrixTranslate( M1, -Fx, -Fy, -Fz);

A = Cx - Fx; B = Cy - Fy; C = Cz - Fz;

d1 = (float)Math::Sqrt(A * A + C * C); if (d1 != 0)

{

sin1 = -A / d1; cos1 = C / d1;

}

d2 = (float)Math::Sqrt(A * A + B * B + C * C); if (d2 != 0)

{

sin2 = B / d2; cos2 = d1 / d2;

}

//Вращаем объект вокруг оси y, чтобы разместить //центр проекции в y-z плоскости: MatrixIdentity(M2);

//Если d1 = 0, тогда центр проекции

//уже находится на оси y и в y-z плоскости: if (d1 != 0)

74 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005

{

M2[1, 1] = cos1; M2[1, 3] = -sin1; M2[3, 1] = sin1; M2[3, 3] = cos1;

}

//Вращаем вокруг оси x,

//чтобы разместить центр проекции на оси z: MatrixIdentity(M3);

//Если d2 = 0, то центр проекции //находится в начале координат. //Это делает проекцию невозможной: if (d2 != 0)

{

M3[2, 2] = cos2; M3[2, 3] = sin2; M3[3, 2] = -sin2; M3[3, 3] = cos2;

}

//Вращаем вектор UP:

up1[1] = ux; up1[2] = uy; up1[3] = uz; up1[4] = 1;

MatrixApply( up1, M2, up2); MatrixApply( up2, M3, up1);

//Вращаем вокруг оси z, чтобы разместить //вектор UP в y-z плоскости:

d3 = (float)Math::Sqrt(up1[1] * up1[1] + up1[2] * up1[2]);

MatrixIdentity( M4);

//Если d3 = 0, то вектор UP равен нулю: if (d3 != 0)

{

sin3 = up1[1] / d3; cos3 = up1[2] / d3; M4[1, 1] = cos3; M4[1, 2] = sin3; M4[2, 1] = -sin3; M4[2, 2] = cos3;

}

//Проецируем:

if (type_of_projection == PerspectiveProjection) MatrixPerspectiveXZ( M5, d2);

else

MatrixIdentity( M5); if (d2 != 0)

MatrixPerspectiveXZ( M5, d2); else

MatrixIdentity( M5); //Комбинируем преобразования: m3MatMultiply( M12, M1, M2); m3MatMultiply( M34, M3, M4); m3MatMultiply( M1234, M12, M34);

if (type_of_projection == PerspectiveProjection) m3MatMultiplyFull( M, M1234, M5);

Глава 24. Изображение и управление трехмерными объектами

75

else

m3MatMultiply( M, M1234, M5);

}

//Строим матрицу преобразования (3-D transformation matrix) //для перспективного проецирования (perspective projection): //центр проецирования (r, phi, theta),

//фокус (fx, fy, fx),

//вектор от объекта до экрана UP <ux, yx, uz>, //тип проецирования (type_of_projection): //PerspectiveProjection:

public: void Projection( array<float,2>^ M, int type_of_projection, float R,

float phi, float theta, float Fx, float Fy, float Fz, float ux, float uy, float uz)

{

float Cx, Cy, Cz, r2;

//Переходим к прямоугольным координатам: Cy = R * (float)Math::Sin(phi);

r2 = R * (float)Math::Cos(phi); Cx = r2 * (float)Math::Cos(theta); Cz = r2 * (float)Math::Sin(theta);

MatrixTransformation( M, type_of_projection, Cx, Cy, Cz, Fx, Fy, Fz, ux, uy, uz); // M

}

//Строим матрицу преобразования, чтобы получить //отражение напротив плоскости, проходящей

//через (p1, p2, p3) с вектором нормали <n1, n2, n3>:

public: void m3Reflect( array<float,2>^ M, float p1, float p2, float p3,

float n1, float n2, float n3)

{

array<float,2>^ T =

gcnew array<float,2>(5, 5);//Перенос. array<float,2>^ R1 =

gcnew array<float,2>(5, 5); //Вращение 1. array<float,2>^ r2 =

gcnew array<float,2>(5, 5); //Вращение 2. array<float,2>^ S =

gcnew array<float,2>(5, 5); //Отражение. array<float,2>^ R2i =

gcnew array<float,2>(5, 5); //Не вращать 2. array<float,2>^ R1i =

gcnew array<float,2>(5, 5); //Не вращать 1. array<float,2>^ Ti =

gcnew array<float,2>(5, 5); //Не переносить.

76 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005

float D, L;

array<float,2>^ M12 = gcnew array<float,2>(5, 5); array<float,2>^ M34 = gcnew array<float,2>(5, 5); array<float,2>^ M1234 = gcnew array<float,2>(5, 5); array<float,2>^ M56 = gcnew array<float,2>(5, 5); array<float,2>^ M567 = gcnew array<float,2>(5, 5); //Переносим плоскость к началу координат: MatrixTranslate( T, -p1, -p2, -p3); MatrixTranslate( Ti, p1, p2, p3);

//Вращаем вокруг оси z,

//пока нормаль не будет в y-z плоскости: MatrixIdentity( R1);

D = (float)Math::Sqrt(n1 * n1 + n2 * n2); R1[1, 1] = n2 / D; R1[1, 2] = n1 / D; R1[2, 1] = -R1[1, 2]; R1[2, 2] = R1[1, 1]; MatrixIdentity( R1i);

R1i[1, 1] = R1[1, 1]; R1i[1, 2] = -R1[1, 2]; R1i[2, 1] = -R1[2, 1]; R1i[2, 2] = R1[2, 2];

//Вращаем вокруг оси x, когда нормаль будет по оси y: MatrixIdentity( r2);

L = (float)Math::Sqrt(n1 * n1 + n2 * n2 + n3 * n3); r2[2, 2] = D / L; r2[2, 3] = -n3 / L;

r2[3, 2] = -r2[2, 3]; r2[3, 3] = r2[2, 2]; MatrixIdentity( R2i);

R2i[2, 2] = r2[2, 2]; R2i[2, 3] = -r2[2, 3]; R2i[3, 2] = -r2[3, 2]; R2i[3, 3] = r2[3, 3];

//Рисуем отражение объекта перпендикулярно x-z плоскости: MatrixIdentity( S); S[2, 2] = -1;

//Комбинируем матрицы: m3MatMultiply( M12, T, R1); m3MatMultiply( M34, r2, S); m3MatMultiply( M1234, M12, M34); m3MatMultiply( M56, R2i, R1i); m3MatMultiply( M567, M56, Ti); m3MatMultiply( M, M1234, M567);

}

//Строим матрицу преобразования для поворота на угол theta //вокруг линии, проходящей через (p1, p2, p3)

//в направлении <d1, d2, d3>.

//Угол theta откладывается против часовой стрелки, //если мы смотрим вниз в направлении, //противоположном направлению линии:

public: void m3LineRotate( array<float,2>^ M, float p1, float p2, float p3,

float d1, float d2, float d3, float theta)

{

array<float,2>^ T =

Глава 24. Изображение и управление трехмерными объектами

77

gcnew array<float,2>(5, 5);//Перенос.

 

array<float,2>^ R1 =

 

 

 

 

gcnew array<float,2>(5, 5); //Вращение 1.

 

array<float,2>^ r2 =

 

 

 

 

gcnew array<float,2>(5, 5); //Вращение 2.

 

array<float,2>^ Rot3 =

 

 

 

gcnew array<float,2>(5, 5); //Отражение.

 

array<float,2>^ R2i =

 

 

 

 

gcnew array<float,2>(5, 5); //Не вращать 2.

 

array<float,2>^ R1i =

 

 

 

 

gcnew array<float,2>(5, 5); //Не вращать 1.

 

array<float,2>^ Ti =

 

 

 

 

gcnew array<float,2>(5, 5); //Не переносить.

 

float D, L;

 

 

 

 

array<float,2>^ M12 = gcnew array<float,2>(5, 5);

 

array<float,2>^ M34 = gcnew array<float,2>(5, 5);

 

array<float,2>^ M1234 = gcnew array<float,2>(5, 5);

 

array<float,2>^ M56 = gcnew array<float,2>(5, 5);

 

array<float,2>^ M567 = gcnew array<float,2>(5, 5);

 

//Переносим плоскость к началу координат:

 

MatrixTranslate( T, -p1, -p2, -p3);

 

MatrixTranslate( Ti, p1, p2, p3);

 

//Вращаем вокруг оси z,

 

 

 

//пока линия не окажется в y-z плоскости:

 

MatrixIdentity( R1);

 

 

 

 

D = (float)Math::Sqrt(d1 * d1 + d2 * d2);

 

R1[1, 1] = d2 / D; R1[1, 2] = d1 / D;

 

R1[2, 1] = -R1[1, 2]; R1[2, 2] = R1[1, 1];

 

MatrixIdentity( R1i);

 

 

 

 

R1i[1, 1] = R1[1, 1]; R1i[1, 2] = -R1[1, 2];

 

R1i[2, 1] = -R1[2, 1]; R1i[2, 2] = R1[2, 2];

 

//Вращаем вокруг оси x, когда линия будет по оси y:

 

MatrixIdentity( r2);

 

 

 

 

L = (float)Math::Sqrt(d1 * d1 + d2 * d2 + d3 * d3);

 

r2[2, 2] = D / L; r2[2, 3] = -d3 / L;

 

r2[3, 2] = -r2[2, 3]; r2[3, 3] = r2[2, 2];

 

MatrixIdentity( R2i);

 

 

 

 

R2i[2, 2] = r2[2, 2]; R2i[2, 3] = -r2[2, 3];

 

R2i[3, 2] = -r2[3, 2]; R2i[3, 3] = r2[3, 3];

 

//Вращаем вокруг линии (оси y):

 

MatrixYRotate( Rot3, theta);

 

//Комбинируем матрицы:

R1);

 

m3MatMultiply( M12,

T,

 

m3MatMultiply( M34,

r2,

Rot3);

 

m3MatMultiply( M1234,

M12,

M34);

 

m3MatMultiply( M56,

R2i,

 

R1i);

 

m3MatMultiply( M567,

M56,

Ti);

 

78 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005

m3MatMultiply( M, M1234, M567);

}

//Строим матрицу преобразования (3-D transformation matrix) //для переноса на Tx, Ty, Tz:

public: void MatrixTranslate( array<float,2>^ M, float Tx, float Ty, float Tz)

{

MatrixIdentity( M);

M[4, 1] = Tx; M[4, 2] = Ty; M[4, 3] = Tz;

}

//Строим матрицу преобразования (3-D transformation matrix) //для поворота вокруг оси y (угол - в радианах):

public: void MatrixYRotate( array<float,2>^ M, float theta)

{

MatrixIdentity( M);

M[1, 1] = (float)Math::Cos(theta); M[3, 3] = M[1, 1];

M[3, 1] = (float)Math::Sin(theta); M[1, 3] = -M[3, 1];

}

//Применяем матрицу преобразования к точке, //где матрица не может иметь 0, 0, 0, 1 //в последнем столбце. Нормализуем только

//x и y компоненты результата, чтобы сохранить z информацию: public: void MatrixApplyFull(array<float>^ V,

array<float,2>^ M, array<float>^ Result)

{

int i, j; float value = 0; for (i = 1; i <= 4; i++)

{

value = 0;

for (j = 1; j <= 4; j++)

{

value = value + V[j] * M[j, i];

}

Result[i] = value;

}

//Повторно нормализуем точку (value = Result[4]): if (value != 0)

{

Result[1] = Result[1] / value; Result[2] = Result[2] / value;

}

else

{

//Не преобразовываем z - составляющую.

//Если значение z больше, чем от центра проекции,

Глава 24. Изображение и управление трехмерными объектами

79

//эта точка будет удалена: Result[3] = Single::MaxValue;

}

Result[4] = 1;

}

//Применяем матрицу преобразования к точке: public: void MatrixApply(array<float>^ V, array<float,2>^ M, array<float>^ Result)

{

Result[1] = V[1] *

M[1, 1] + V[2] * M[2, 1] +

V[3] * M[3, 1]

+ M[4, 1];

Result[2] = V[1] *

M[1, 2] + V[2] * M[2, 2] +

V[3] * M[3, 2]

+ M[4, 2];

Result[3] = V[1] *

M[1, 3] + V[2] * M[2, 3] +

V[3] * M[3, 3] + M[4, 3]; Result[4] = 1;

}

//Умножаем две матрицы. Матрицы //не могут содержать 0, 0, 0, 1 в последних столбцах:

public: void m3MatMultiplyFull(array<float,2>^ Result, array<float,2>^ A, array<float,2>^ B)

{

int i, j, k; float value; for (i = 1; i <= 4; i++)

{

for (j = 1; j <= 4; j++)

{

value = 0;

for (k = 1; k <= 4; k++)

value = value + A[i, k] * B[k, j]; Result[i, j] = value;

}

}

}

//Умножаем две матрицы:

public: void m3MatMultiply(array<float,2>^ Result, array<float,2>^ A, array<float,2>^ B)

{

Result[1, 1] = A[1, 1] * B[1, 1] + A[1, 2] * B[2, 1] + A[1, 3] * B[3, 1];

Result[1, 2] = A[1, 1] * B[1, 2] + A[1, 2] * B[2, 2] + A[1, 3] * B[3, 2];

Result[1, 3] = A[1, 1] * B[1, 3] + A[1, 2] * B[2, 3] + A[1, 3] * B[3, 3];

Result[1, 4] = 0;

Result[2, 1] = A[2, 1] * B[1, 1] + A[2, 2] * B[2, 1]

Соседние файлы в предмете Программирование на C++