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

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

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

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

m3MatMultiply(M, M1234, M567) End Sub

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

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

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

Public Sub m3LineRotate(ByRef M(,) As Single, _

ByVal p1 As Single, ByVal p2 As Single, ByVal p3 As Single, _ ByVal d1 As Single, ByVal d2 As Single, ByVal d3 As Single, _ ByVal theta As Single)

Dim T(4, 4) As Single 'Перенос. Dim R1(4, 4) As Single 'Вращение 1. Dim r2(4, 4) As Single 'Вращение 2. Dim Rot3(4, 4) As Single 'Вращение.

Dim R2i(4, 4) As Single 'Стоп вращению 2. Dim R1i(4, 4) As Single 'Стоп вращению 1. Dim Ti(4, 4) As Single 'Стоп переносу.

Dim D As Single : Dim L As Single

Dim M12(4, 4) As Single : Dim M34(4, 4) As Single Dim M1234(4, 4) As Single

Dim M56(4, 4) As Single : Dim M567(4, 4) As Single 'Переносим плоскость к началу координат: MatrixTranslate(T, -p1, -p2, -p3) MatrixTranslate(Ti, p1, p2, p3)

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

'пока линия не окажется в y-z плоскости: MatrixIdentity(R1)

D = CSng(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 = CSng(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)

'Комбинируем матрицы: m3MatMultiply(M12, T, R1)

Глава 25. Изображение и управление объектами на VB и VC++

101

m3MatMultiply(M34, r2, Rot3) m3MatMultiply(M1234, M12, M34) m3MatMultiply(M56, R2i, R1i) m3MatMultiply(M567, M56, Ti) m3MatMultiply(M, M1234, M567)

End Sub

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

Public Sub MatrixTranslate(ByRef M(,) As Single, _

ByVal Tx As Single, ByVal Ty As Single, ByVal Tz As Single) MatrixIdentity(M)

M(4, 1) = Tx : M(4, 2) = Ty : M(4, 3) = Tz End Sub

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

Public Sub MatrixYRotate(ByRef M(,) As Single, _ ByVal theta As Single)

MatrixIdentity(M)

M(1, 1) = CSng(Cos(theta)) M(3, 3) = M(1, 1)

M(3, 1) = CSng(Sin(theta)) M(1, 3) = -M(3, 1)

End Sub

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

'x и y компоненты результата, чтобы сохранить z информацию: Public Sub MatrixApplyFull(ByRef V() As Single, _

ByRef M(,) As Single, ByRef Result() As Single) Dim i As Integer : Dim j As Integer

Dim value As Single For i = 1 To 4

value = 0

For j = 1 To 4

value = value + V(j) * M(j, i) Next j

Result(i) = value Next i

'Повторно нормализуем точку (value = Result(4)): If value <> 0 Then

Result(1) = Result(1) / value Result(2) = Result(2) / value

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

'Если значение z больше, чем от центра проекции, 'эта точка будет удалена:

Result(3) = Single.MaxValue

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

End If Result(4) = 1

End Sub

'Применяем матрицу преобразования к точке: Public Sub MatrixApply(ByRef V() As Single, _ ByRef M(,) As Single, ByRef Result() As Single)

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 End Sub

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

Public Sub m3MatMultiplyFull(ByRef Result(,) As Single, _ ByRef A(,) As Single, ByRef B(,) As Single)

Dim i As Integer : Dim j As Integer Dim k As Integer : Dim value As Single For i = 1 To 4

For j = 1 To 4 value = 0

For k = 1 To 4

value = value + A(i, k) * B(k, j) Next k

Result(i, j) = value Next

Next End Sub

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

Public Sub m3MatMultiply(ByRef Result(,) As Single, _ ByRef A(,) As Single, ByRef B(,) As Single)

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) _

+A(2, 3) * B(3, 1)

Result(2, 2) = A(2, 1) * B(1, 2) + A(2, 2) * B(2, 2) _ + A(2, 3) * B(3, 2)

Result(2, 3) = A(2, 1) * B(1, 3) + A(2, 2) * B(2, 3) _ + A(2, 3) * B(3, 3)

Result(2, 4) = 0

Глава 25. Изображение и управление объектами на VB и VC++

103

Result(3, 1) = A(3,

1) * B(1, 1)

+ A(3,

2) * B(2, 1)

_

+ A(3, 3)

* B(3, 1)

1)

* B(1, 2)

+ A(3,

2)

* B(2, 2)

_

Result(3, 2) = A(3,

+ A(3, 3)

* B(3, 2)

1)

* B(1, 3)

+ A(3,

2)

* B(2, 3)

_

Result(3, 3) = A(3,

+A(3, 3) * B(3, 3) Result(3, 4) = 0

Result(4, 1) = A(4, 1) * B(1, 1) + A(4, 2) * B(2, 1) _

+A(4, 3) * B(3, 1) + B(4, 1)

Result(4, 2) = A(4, 1) * B(1, 2) + A(4, 2) * B(2, 2) _ + A(4, 3) * B(3, 2) + B(4, 2)

Result(4, 3) = A(4, 1) * B(1, 3) + A(4, 2) * B(2, 3) _ + A(4, 3) * B(3, 3) + B(4, 3)

Result(4, 4) = 1 End Sub

Листинг 25.4. Метод на VB для печати изображения с элемента PictureBox.

Private Sub PrintDocument1_PrintPage( _ ByVal sender As System.Object, _

ByVal e As System.Drawing.Printing.PrintPageEventArgs) _ Handles PrintDocument1.PrintPage

e.Graphics.DrawImage(PictureBox1.Image, 0, 0) End Sub

Глава 26. Изображение и управление трехмерными объектами на Visual C# для интеграции с Visual C++, Visual Basic и дру-

гими языками

Листинг 26.1. Код выше и в теле метода Form1_Load.

//Начало координат:

private const double x_focus = 0; private const double y_focus = 0; private const double z_focus = 0;

//Сферические координаты глаза наблюдателя (точки E): private float r_Eye;

private float phi_Eye; private float theta_Eye;

//Объявляем переменные и матрицу (как массив) MatrixProjection

//(во всех массивах нулевые индексы не используем): private const double pi = Math.PI;

private int Tetrahedron; private int Cube; private int Octahedron; private int Dodecahedron;

private int Icosahedron_first; private int Icosahedron_last;

private float[,] MatrixProjection = new float[5, 5]; //Для параллельного проецирования объекта на экран

//(parallel projection) задаем константу: private const int ParallelProjection = 0;

//Для перспективного проецирования объекта на экран

//(perspective projection) задаем константу: private const int PerspectiveProjection = 1;

private void Form1_Load(object sender, EventArgs e)

{

//Задаем координаты глаза наблюдателя, например: r_Eye = 4;

phi_Eye = (float)(0.05 * pi); theta_Eye = (float)(0.3 * pi);

//Вызываем метод для перспективного проецирования, //когда type_of_projection = PerspectiveProjection //(для параллельного проецирования вместо

Глава 26. Изображение и управление объектами на VC# и VC++

105

//PerspectiveProjection пишем ParallelProjection): Projection(ref MatrixProjection, PerspectiveProjection, r_Eye, phi_Eye, theta_Eye,

(float)x_focus, (float)y_focus, (float)z_focus, 0, 1, 0); //Рассчитываем параметры геометрического тела:

СalculateParameters();

//Связываем элемент PictureBox1 с классом Bitmap: pictureBox1.Image = new Bitmap(pictureBox1.Width,

pictureBox1.Height); //Проектируем и в PictureBox рисуем выбранное нами тело: Designing((Bitmap)pictureBox1.Image);

}

Листинг 26.2. Метод ProcessCmdKey.

protected override bool ProcessCmdKey( ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)

{

//Задаем угол поворота фигуры после нажатия клавиши: const float delta_theta = (float)pi / 20; ; //Рассчитываем новые координаты глаза наблюдателя: if (keyData == System.Windows.Forms.Keys.Left)

theta_Eye = theta_Eye - delta_theta;

if (keyData == System.Windows.Forms.Keys.Right) theta_Eye = theta_Eye + delta_theta;

if (keyData == System.Windows.Forms.Keys.Up) phi_Eye = phi_Eye - delta_theta;

if (keyData == System.Windows.Forms.Keys.Down) phi_Eye = phi_Eye + delta_theta;

//Проектируем выбранное нами геометрическое тело: Projection(ref MatrixProjection, PerspectiveProjection,

r_Eye, phi_Eye, theta_Eye,

(float)x_focus, (float)y_focus, (float)z_focus, 0, 1, 0);

Designing((Bitmap)pictureBox1.Image);

//В элементе PictureBox перерисовываем объект: pictureBox1.Refresh();

return true;

}

Листинг 26.3. Методы для решения поставленной задачи.

//Проектируем и при помощи процедуры DrawSolid //рисуем выбранное флажком CheckBox геом-е тело: private void Designing(Bitmap bmp)

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

{

//Создаем объект g класса Graphics: Graphics g;

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

//Задаем белый цвет типа Window

//для элемента управления PictureBox1: g.Clear(SystemColors.Window);

//Высвобождаем ресурсы от графического объекта g: g.Dispose();

//Преобразуем точки: TransformAllDataFull(ref MatrixProjection);

//Проектируем и рисуем выбранное на CheckBox тело: if (checkBox1.CheckState ==

System.Windows.Forms.CheckState.Checked)

{

DrawSolid(

bmp, Tetrahedron, Cube - 1, System.Drawing.Color.Red, false);

}

if (checkBox2.CheckState == System.Windows.Forms.CheckState.Checked)

{

DrawSolid(bmp, Cube, Octahedron - 1, System.Drawing.Color.Black, false);

}

if (checkBox3.CheckState == System.Windows.Forms.CheckState.Checked)

{

DrawSolid(bmp, Octahedron, Dodecahedron - 1, System.Drawing.Color.Green, false);

}

if (checkBox4.CheckState == System.Windows.Forms.CheckState.Checked)

{

DrawSolid(bmp, Dodecahedron, Icosahedron_first - 1, System.Drawing.Color.Blue, false);

}

if (checkBox5.CheckState == System.Windows.Forms.CheckState.Checked)

{

DrawSolid(bmp, Icosahedron_first, Icosahedron_last, System.Drawing.Color.Orange, false);

}

if (checkBox6.CheckState == System.Windows.Forms.CheckState.Checked)

{

Глава 26. Изображение и управление объектами на VC# и VC++

107

DrawSolid(bmp, 1, Tetrahedron - 1, System.Drawing.Color.Salmon, false);

}

}

//Рассчитываем параметры геометрических тел и осей: private void СalculateParameters()

{

float theta1; float theta2;

float s1; float s2; float c1; float c2; float S; float R; float H; float A; float B; float C; float D; float X; float Y; float y2; float M; float N; //Оси координат:

DesigningLine(0, 0, 0, 0.5f, 0, 0); //Ось x. DesigningLine(0, 0, 0, 0, 0.5f, 0); //Ось y. DesigningLine(0, 0, 0, 0, 0, 0.5f); //Ось z. //Тетраэдр (Tetrahedron):

Tetrahedron = NumLines + 1; S = (float)Math.Sqrt(6);

A = (float)(S / Math.Sqrt(3)); B = -A / 2;

C = (float)(A * Math.Sqrt(2) - 1); D = S / 2; DesigningLine(0, C, 0, A, -1, 0); DesigningLine(0, C, 0, B, -1, D); DesigningLine(0, C, 0, B, -1, -D); DesigningLine(B, -1, -D, B, -1, D); DesigningLine(B, -1, D, A, -1, 0); DesigningLine(A, -1, 0, B, -1, -D);

//Куб (Cube):

Cube = NumLines + 1; DesigningLine(-1, -1, -1, -1, 1, -1); DesigningLine(-1, 1, -1, 1, 1, -1); DesigningLine(1, 1, -1, 1, -1, -1); DesigningLine(1, -1, -1, -1, -1, -1); DesigningLine(-1, -1, 1, -1, 1, 1); DesigningLine(-1, 1, 1, 1, 1, 1); DesigningLine(1, 1, 1, 1, -1, 1); DesigningLine(1, -1, 1, -1, -1, 1); DesigningLine(-1, -1, -1, -1, -1, 1); DesigningLine(-1, 1, -1, -1, 1, 1); DesigningLine(1, 1, -1, 1, 1, 1); DesigningLine(1, -1, -1, 1, -1, 1); //Октаэдр (Octahedron):

Octahedron = NumLines + 1; DesigningLine(0, 1, 0, 1, 0, 0); DesigningLine(0, 1, 0, -1, 0, 0); DesigningLine(0, 1, 0, 0, 0, 1); DesigningLine(0, 1, 0, 0, 0, -1);

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

DesigningLine(0, -1, 0, 1, 0, 0);

DesigningLine(0, -1, 0, -1, 0, 0);

DesigningLine(0, -1, 0, 0, 0, 1);

DesigningLine(0, -1, 0, 0, 0, -1);

DesigningLine(0, 0, 1, 1, 0, 0);

DesigningLine(0, 0, 1, -1, 0, 0);

DesigningLine(0, 0, -1, 1, 0, 0);

DesigningLine(0, 0, -1, -1, 0, 0); //ДОдекаэдр (Dodecahedron): Dodecahedron = NumLines + 1;

theta1 = (float)(pi * 0.4); theta2 = (float)(pi * 0.8); s1 = (float)Math.Sin(theta1);

c1 = (float)Math.Cos(theta1);

s2 = (float)Math.Sin(theta2);

c2 = (float)Math.Cos(theta2);

M = 1 - (2 - 2 * c1 - 4 * s1 * s1) / (2 * c1 - 2); N = (float)Math.Sqrt((2 - 2 * c1) - M * M) *

(1 + (1 - c2) / (c1 - c2)); R = 2 / N; S = (float)(R * Math.Sqrt(2 - 2 * c1));

A = R * s1; B = R * s2; C = R * c1; D = R * c2; H = R * (c1 - s1);

X = (R * R * (2 - 2 * c1) - 4 * A * A) / (2 * C - 2 * R);

Y = (float)Math.Sqrt(S * S - (R - X) * (R - X)); y2 = Y * (1 - c2) / (c1 - c2);

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

DesigningLine(C, 1, A, D, 1, B);

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

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

DesigningLine(C, 1, -A, R, 1, 0); DesigningLine(R, 1, 0, X, 1 - Y, 0); DesigningLine(C, 1, A, X * c1, 1 - Y, X * s1); DesigningLine(C, 1, -A, X * c1, 1 - Y, -X * s1); DesigningLine(D, 1, B, X * c2, 1 - Y, X * s2); DesigningLine(D, 1, -B, X * c2, 1 - Y, -X * s2);

DesigningLine(X, 1 - Y, 0, -X * c2, 1 - y2, -X * s2); DesigningLine(X, 1 - Y, 0, -X * c2, 1 - y2, X * s2); DesigningLine(X * c1, 1 - Y, X * s1,

-X * c2, 1 - y2, X * s2); DesigningLine(X * c1, 1 - Y, X * s1,

-X * c1, 1 - y2, X * s1); DesigningLine(X * c2, 1 - Y, X * s2,

-X * c1, 1 - y2, X * s1); DesigningLine(X * c2, 1 - Y, X * s2, -X, 1 - y2, 0); DesigningLine(X * c2, 1 - Y, -X * s2, -X, 1 - y2, 0); DesigningLine(X * c2, 1 - Y, -X * s2,

-X * c1, 1 - y2, -X * s1);

Глава 26. Изображение и управление объектами на VC# и VC++

109

DesigningLine(X * c1,

1 - Y, -X * s1,

 

-X *

c1,

1 - y2, -X * s1);

 

DesigningLine(X * c1,

1 -

Y, -X * s1,

 

-X *

c2,

1 - y2, -X * s2);

 

DesigningLine(-R, -1,

0, -X, 1 - y2, 0);

 

DesigningLine(-C, -1,

A, -X * c1, 1 - y2, X * s1);

 

DesigningLine(-D, -1,

B, -X * c2, 1 - y2, X * s2);

 

DesigningLine(-D, -1,

-B, -X * c2, 1 - y2, -X * s2);

 

DesigningLine(-C, -1,

-A, -X * c1, 1 - y2, -X * s1);

 

DesigningLine(-R, -1,

0, -C, -1, A);

 

DesigningLine(-C, -1,

A, -D, -1, B);

 

DesigningLine(-D, -1,

B, -D, -1, -B);

 

DesigningLine(-D, -1,

-B, -C, -1, -A);

 

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

 

//Икосаэдр (Icosahedron):

 

 

Icosahedron_first = NumLines + 1;

 

R = (float)(2f / (2f * Math.Sqrt(1 - 2f * c1) +

 

Math.Sqrt(3f / 4f

* (2f - 2f * c1) -

 

2f * c2 - c2 * c2

- 1f)));

 

S = R * (float)Math.Sqrt(2 - 2 * c1);

H = 1 - (float)Math.Sqrt(S * S - R * R);

A = R * s1; B = R * s2; C = R * c1; D = R * c2; 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, -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);

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