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

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

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

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

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 = 2 / (2 * CSng(Sqrt(1 - 2 * c1)) + _ CSng(Sqrt(3 / 4 * (2 - 2 * c1) - _

2 * c2 - c2 * c2 - 1)))

S = R * CSng(Sqrt(2 - 2 * c1))

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

End Sub

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

91

Public Structure Line

'Массивы для соединения точек (points): <VBFixedArray(4)> Dim fr_points() As Single <VBFixedArray(4)> Dim to_points() As Single 'Массивы для соединения преобразованных точек

'(transformed points):

<VBFixedArray(4)> Dim fr_tr_points() As Single <VBFixedArray(4)> Dim to_tr_points() As Single Public Sub Initialize()

ReDim fr_points(4) : ReDim to_points(4) ReDim fr_tr_points(4) : ReDim to_tr_points(4)

End Sub

End Structure

'Объявляем массив Lines структуры Line (создавать массив 'из изменяемого количества элементов и инициализировать его 'при помощи оператора ReDim мы будем ниже):

Public Lines() As Line

'Объявляем и инициализируем переменную для индекса массива: Public NumLines As Integer

'Проектируем линию между точками (x1,y1,z1),(x2,y2,z2): Public Sub DesigningLine(ByVal x1 As Single, _

ByVal y1 As Single, ByVal z1 As Single, ByVal x2 As Single, _ ByVal y2 As Single, ByVal z2 As Single)

NumLines = NumLines + 1

'Создаем массив Lines структуры Line из изменяемого 'количества элементов NumLines, инициализируем его 'оператором ReDim и при помощи ключевого слова Preserve 'сохраняем предыдущие данные массива:

ReDim Preserve Lines(NumLines) 'Инициализируем и рассчитываем массивы: 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

End Sub

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

'Преобразование не имеет 0, 0, 0, 1 в последнем столбце: Public Sub TransformAllDataFull(ByRef M(,) As Single)

TransformDataFull(M, 1, NumLines) End Sub

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

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

'ко всем выделенным линиям, используя MatrixApplyFull. 'Преобразование не имеет 0, 0, 0, 1 в последнем столбце: Public Sub TransformDataFull(ByRef M(,) As Single, _ ByVal line1 As Integer, ByVal line2 As Integer)

Dim i As Integer

For i = line1 To line2 MatrixApplyFull(Lines(i).fr_points, M, _ Lines(i).fr_tr_points) MatrixApplyFull(Lines(i).to_points, M, _ Lines(i).to_tr_points)

Next i End Sub

'Вводим перем-ю N_Graphics для номера многих геом-х изобр-й. 'Номер первого изображения равен 1:

Dim N_Graphics As Integer = 1

'Рисуем выделенные преобразованные линии и экпорт-м в файлы: Public Sub DrawSolid(ByVal bmp As Bitmap, _

ByVal first_line As Integer, ByVal last_line As Integer, _ ByVal color As Color, ByVal clear As Boolean)

Dim k As Integer

Dim x1 As Single : Dim y1 As Single

Dim x2 As Single : Dim y2 As Single Dim g As Graphics : Dim pen As Pen

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

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

If clear Then g.Clear(System.Drawing.Color.Black) 'Объявляем индексы элементов всех массивов:

Dim i, j As Integer

'Если этот метод DrawSolid вызван второй раз

'для рисования второго изображения и N_Graphics = 2, 'то обходим 1-й массив для первого изобр-я до метки M2: If N_Graphics = 2 Then GoTo M2

'Программируем первый массив для первого изображения: 'Задаем границы индексов первого массива myArrayVB(i, j) Dim N_x As Integer = 200

Dim N_y As Integer = 1

'Объявляем массив myArrayVB(i, j) переменных типа Single, 'когда i = 0,1,2,3,...,N_x; j = 0,1,2,3,...,N_y:

Dim myArrayVB(N_x, N_y) As Single 'Автомат-ки обнуляется. 'Значение первой границы массива myArrayVB:

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

93

Dim N_1_myArrayVB As Integer

 

'Рассчитываем элементы массива myArrayVB(i, j)

 

'для рисования линий первого геом-го изображения:

 

i = -1

'Задаем до цикла.

 

For k = first_line To last_line

 

x1

= Lines(k).fr_tr_points(1)

 

y1

= Lines(k).fr_tr_points(2)

 

x2

= Lines(k).to_tr_points(1)

 

y2

= Lines(k).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) _

')

'Масштабируем значения координат:

x1 = (x1 * bmp.Width / 4) + bmp.Width / 2.0F y1 = bmp.Height / 2.0F - (y1 * bmp.Height / 4) x2 = (x2 * bmp.Width / 4) + bmp.Width / 2.0F y2 = bmp.Height / 2.0F - (y2 * bmp.Height / 4) 'Записываем координаты точек в массив:

i = i + 2 myArrayVB(i, 0) = x1 myArrayVB(i, 1) = y1

myArrayVB(i + 1, 0) = x2 myArrayVB(i + 1, 1) = y2

N_1_myArrayVB = i + 1 'Значение границы массива.

Next

'Начало N_first_line и конец N_last_line цикла

'при рисовании из массива myArrayVB: Dim N_first_line, N_last_line As Integer N_first_line = first_line

N_last_line = last_line

'Передаем значения начала N_first_line

'и конца цикла N_last_line в элементы массива

'myArrayVB(0, 0) и myArrayVB(0, 1): myArrayVB(0, 0) = N_first_line myArrayVB(0, 1) = N_last_line

'Рисуем при помощи массива координат myArrayVB(200, 1). i = -1

For k = N_first_line To N_last_line i = i + 2

x1 = myArrayVB(i, 0)

y1 = myArrayVB(i, 1)

x2 = myArrayVB(i + 1, 0)

y2 = myArrayVB(i + 1, 1)

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

g.DrawLine(pen, x1, y1, x2, y2) Next

'Записываем массив координат myArrayVB(200, 1) в файл. 'Создаем объект sw класса StreamWriter для записи

'в файл по адресу D:\MyDocs\MyTest3D_Graphics.txt. If N_Graphics = 1 Then

Dim sw As StreamWriter = _

New StreamWriter("D:\MyDocs\MyTest3D_Graphics.txt") 'Каждый элемент массива myArrayVB(i, j) записываем в файл 'в виде отдельной строки при помощи процедуры WriteLine: For i = 0 To N_x

For j = 0 To N_y sw.WriteLine(myArrayVB(i, j))

Next Next sw.Close() End If

M2:

'Если этот метод DrawSolid вызван первый раз

'для рисования первого изображения и N_Graphics = 1, 'то обходим 2-й массив для 2-го изобр-я до метки M_End: If N_Graphics = 1 Then GoTo M_End

'Программируем второй массив для второго изображения. 'Задаем границы индексов 2-го массива myArrayVB_2(i, j): Dim N_x_2 As Integer = 200

Dim N_y_2 As Integer = 1

'Задаем массив myArrayVB_2(i, j) переменных типа Single, 'когда i = 0,1,2,3,...,N_x; j = 0,1,2,3,...,N_y:

Dim myArrayVB_2(N_x_2, N_y_2) As Single 'Значение первой границы массива myArrayVB_2: Dim N_1_myArrayVB_2 As Integer

'Рассчитываем элементы массива myArrayVB_2(i, j) 'для рисования линий второго геом-го изображения: i = -1 'Задаем до цикла.

For k = first_line To last_line x1 = Lines(k).fr_tr_points(1) y1 = Lines(k).fr_tr_points(2) x2 = Lines(k).to_tr_points(1) y2 = Lines(k).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) _

')

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

95

'Масштабируем значения координат:

x1 = (x1 * bmp.Width / 4) + bmp.Width / 2.0F y1 = bmp.Height / 2.0F - (y1 * bmp.Height / 4) x2 = (x2 * bmp.Width / 4) + bmp.Width / 2.0F y2 = bmp.Height / 2.0F - (y2 * bmp.Height / 4) 'Записываем координаты точек в массив:

i = i + 2 myArrayVB_2(i, 0) = x1 myArrayVB_2(i, 1) = y1

myArrayVB_2(i + 1, 0) = x2 myArrayVB_2(i + 1, 1) = y2

N_1_myArrayVB_2 = i + 1 'Значение границы массива. Next

'Начало N_first_line_2 и конец N_last_line_2 цикла

'при рисовании из массива myArrayVB_2:

Dim N_first_line_2, N_last_line_2 As Integer N_first_line_2 = first_line

N_last_line_2 = last_line

'Передаем значения начала N_first_line_2

'и конца цикла N_last_line_2 в элементы массива

'myArrayVB_2(0, 0) и myArrayVB_2(0, 1): myArrayVB_2(0, 0) = N_first_line_2 myArrayVB_2(0, 1) = N_last_line_2

'Рисуем при помощи массива координат myArrayVB_2(200, 1): i = -1

For k = N_first_line_2 To N_last_line_2 i = i + 2

x1 = myArrayVB_2(i, 0)

y1 = myArrayVB_2(i, 1)

x2 = myArrayVB_2(i + 1, 0)

y2 = myArrayVB_2(i + 1, 1) g.DrawLine(pen, x1, y1, x2, y2)

Next

'Записываем массив координат myArrayVB_2(200, 1) в файл. 'Создаем объект sw_2 класса StreamWriter для записи

'в файл по адресу D:\MyDocs\MyTest3D_Graphics_2.txt. 'Файл автоматически очищается:

Dim sw_2 As StreamWriter = _

New StreamWriter("D:\MyDocs\MyTest3D_Graphics_2.txt") 'Каждый элемент массива myArrayVB_2(i, j) запис-м в файл 'в виде отдельной строки при помощи процедуры WriteLine: For i = 0 To N_x_2

For j = 0 To N_y_2 sw_2.WriteLine(myArrayVB_2(i, j))

Next Next sw_2.Close()

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

'Высвобождаем ресурсы от объектов g и pen:

g.Dispose() : pen.Dispose() M_End:

'Если этот метод DrawSolid вызван еще раз 'для рисования следующего изображения,

'то увеличиваем номер изображения N_Graphics на 1: N_Graphics = N_Graphics + 1

End Sub

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

Public Sub MatrixIdentity(ByRef M(,) As Single) Dim i As Integer : Dim j As Integer

For i = 1 To 4 For j = 1 To 4

If i = j Then M(i, j) = 1

Else

M(i, j) = 0 End If

Next Next

End Sub

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

'и c центром проецирования на расстоянии (0, 0, Distance): Public Sub MatrixPerspectiveXZ(ByRef M(,) As Single, _ ByVal Distance As Single)

MatrixIdentity(M)

If Distance <> 0 Then M(3, 4) = -1 / Distance End Sub

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

'центр проецирования (cx, cy, cz), 'фокус (fx, fy, fx),

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

Public Sub MatrixTransformation(ByRef M(,) As Single, _ ByVal type_of_projection As Integer, _

ByVal Cx As Single, _

ByVal Cy As Single, ByVal Cz As Single, _

ByVal Fx As Single, ByVal Fy As Single, _ ByVal Fz As Single, ByVal ux As Single, _ ByVal uy As Single, ByVal uz As Single)

Static M1(4, 4) As Single : Static M2(4, 4) As Single Static M3(4, 4) As Single : Static M4(4, 4) As Single Static M5(4, 4) As Single : Static M12(4, 4) As Single

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

97

Static M34(4, 4) As Single

Static M1234(4, 4) As Single

Dim sin1 As Single : Dim cos1 As Single Dim sin2 As Single : Dim cos2 As Single Dim sin3 As Single : Dim cos3 As Single Dim A As Single : Dim B As Single

Dim C As Single : Dim d1 As Single

Dim d2 As Single : Dim d3 As Single

Dim up1(4) As Single : Dim up2(4) As Single 'Переносим фокус (центр объекта) в начало координат: MatrixTranslate(M1, -Fx, -Fy, -Fz)

A = Cx - Fx : B = Cy - Fy : C = Cz - Fz d1 = CSng(Sqrt(A * A + C * C))

If d1 <> 0 Then

sin1 = -A / d1 : cos1 = C / d1 End If

d2 = CSng(Sqrt(A * A + B * B + C * C)) If d2 <> 0 Then

sin2 = B / d2 : cos2 = d1 / d2 End If

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

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

'уже находится на оси y и в y-z плоскости: If d1 <> 0 Then

M2(1, 1) = cos1 : M2(1, 3) = -sin1 M2(3, 1) = sin1 : M2(3, 3) = cos1

End If

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

'чтобы разместить центр проекции на оси Z. MatrixIdentity(M3)

'Если d2 = 0, то центр проекции 'находится в начале координат. 'Это делает проекцию невозможной. If d2 <> 0 Then

M3(2, 2) = cos2 : M3(2, 3) = sin2 M3(3, 2) = -sin2 : M3(3, 3) = cos2

End If

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

up1(1) = ux : up1(2) = uy : up1(3) = uz up1(4) = 1 : MatrixApply(up1, M2, up2) MatrixApply(up2, M3, up1)

'Rotate around the Z axis to put the UP

'vector in the Y-Z plane.

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

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

d3 = CSng(Sqrt(up1(1) * up1(1) + _ up1(2) * up1(2))) MatrixIdentity(M4)

'Если d3 = 0, то вектор UP равен нулю: If d3 <> 0 Then

sin3 = up1(1) / d3 : cos3 = up1(2) / d3 M4(1, 1) = cos3 : M4(1, 2) = sin3 M4(2, 1) = -sin3 : M4(2, 2) = cos3

End If 'Проецируем:

If type_of_projection = _ PerspectiveProjection And d2 <> 0 Then

MatrixPerspectiveXZ(M5, d2) Else

MatrixIdentity(M5) End If

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

If type_of_projection = PerspectiveProjection Then m3MatMultiplyFull(M, M1234, M5)

Else

m3MatMultiply(M, M1234, M5) End If

End Sub

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

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

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

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

ByVal type_of_projection As Integer, ByVal R As Single, _ ByVal phi As Single, ByVal theta As Single, _

ByVal Fx As Single, ByVal Fy As Single, ByVal Fz As Single, _ ByVal ux As Single, ByVal uy As Single, ByVal uz As Single)

Dim Cx As Single : Dim Cy As Single

Dim Cz As Single : Dim r2 As Single 'Переходим к прямоугольным координатам: Cy = R * CSng(Sin(phi))

r2 = R * CSng(Cos(phi)) Cx = r2 * CSng(Cos(theta)) Cz = r2 * CSng(Sin(theta))

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

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

99

End Sub

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

'через (p1, p2, p3) с вектором нормали <n1, n2, n3>: Public Sub m3Reflect(ByRef M(,) As Single, _

ByVal p1 As Single, ByVal p2 As Single, _

ByVal p3 As Single, ByVal n1 As Single, _

ByVal n2 As Single, ByVal n3 As Single)

Dim T(4, 4) As Single 'Перенос. Dim R1(4, 4) As Single 'Вращение 1. Dim r2(4, 4) As Single 'Вращение 2. Dim S(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(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 = CSng(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)

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