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

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

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

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

y = j + y_min

'Координата z точек поверхности z = f(x, y): z = f(x, y)

Points(i, j) = New myClassPoint3D(x, y, z)

Next

 

Next

 

'Инициализация осей (axes) координат:

'Начало коорд-т.

Axes(0) = New myClassPoint3D(0, 0, 0)

Axes(1) = New myClassPoint3D(30, 0, 0)

'Ось (axis) x.

Axes(2) = New myClassPoint3D(0, 30, 0)

'Ось y.

Axes(3) = New myClassPoint3D(0, 0, 30)

'Ось z.

End Sub

 

Листинг 30.2. Метод PictureBox1_Paint для рисования поверхности.

Private Sub PictureBox1_Paint(ByVal sender As Object, _ ByVal e As System.Windows.Forms.PaintEventArgs) _ Handles PictureBox1.Paint

'Масштабируем все графические объекты на PictureBox1. 'Коэффициенты масштабирования:

Dim M_1 As Single = 29

Dim M_2 As Single = 31 e.Graphics.ScaleTransform( _ PictureBox1.Size.Width / M_1, _ -PictureBox1.Size.Height / M_2, _ MatrixOrder.Append)

Dim M_3 As Single = 2

Dim M_4 As Single = 2 e.Graphics.TranslateTransform( _ PictureBox1.Size.Width / M_3, _ PictureBox1.Size.Height / M_4, _ MatrixOrder.Append)

'Задавая M_1, M_2, M_3, M_4 другие значения,

'мы будем смещать поверхность по отношению к осям x,y,z. 'Матрица преобразования (transformation matrix):

Dim tr As myClassMatrix3D = CalculateTransformation() 'Применяем матрицу преобразования к точкам:

For x As Integer = 0 To x_max For y As Integer = 0 To y_max

Points(x, y).Transformation(tr) Next

Next

'Объявляем индексы элементов массива myArrayVB(i, j): Dim i, j As Integer

'Задаем границы индексов массива myArrayVB(i, j): Dim N_x As Integer = 2000

Глава 30. Изображение и управление поверхностями на VB для VC++, VC# 141

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

'Первая, вторая и третья границы массива, разделяющие 'линии поверхности, параллельные xz, yz, и оси:

Dim N_1_myArrayVB, N_2_myArrayVB, _ N_3_myArrayVB As Integer

'Рассчитываем элементы массива myArrayVB(i, j) 'для рисования линий поверхности, 'параллельных плоскости координат xz:

Dim x1, y1, x2, y2 As Single i = -2 'Задаем до циклов. For x As Integer = 0 To x_max

With Points(x, 0)

x2 = .trans_coord(0)

y2 = .trans_coord(1) End With

For y As Integer = 1 To y_max x1 = x2 : y1 = y2

With Points(x, y)

x2 = .trans_coord(0)

y2 = .trans_coord(1) End With

'Можно рисовать линии поверхности и здесь: 'e.Graphics.DrawLine(myPen, x1, y1, x2, y2) 'Записываем в массив координат:

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

Next

'Рассчитываем элементы массива myArrayVB(i, j) 'для рисования линий поверхности, 'параллельных плоскости координат yz:

i = N_1_myArrayVB - 1

For y As Integer = 0 To y_max With Points(0, y)

x2 = .trans_coord(0)

y2 = .trans_coord(1) End With

For x As Integer = 1 To x_max x1 = x2 : y1 = y2

With Points(x, y)

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

x2 = .trans_coord(0)

y2 = .trans_coord(1) End With

'Можно рисовать линии поверхности и здесь: 'e.Graphics.DrawLine(myPen, x1, y1, x2, y2) 'Записываем в массив координат:

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

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

N_2_myArrayVB = i + 1 'Вторая граница в массиве. Next

Next

'Преобразовываем оси(axes): For k As Integer = 0 To 3

Axes(k).Transformation(tr) Next

'Рассчитываем элементы массива для рисования осей: i = N_2_myArrayVB - 1

x1 = Axes(0).trans_coord(0)

y1 = Axes(0).trans_coord(1)

For k As Integer = 1 To 3

x2 = Axes(k).trans_coord(0)

y2 = Axes(k).trans_coord(1)

'Можно рисовать оси координат и здесь: 'e.Graphics.DrawLine(myPen, x1, y1, x2, y2) 'Записываем в массив координат:

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

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

N_3_myArrayVB = i + 1 'Число всех чисел в массиве. Next

'Рисуем при помощи массива координат myArrayVB(2000, 1). 'Рисуем линии, параллельные плоскости xz:

Dim myPen As New Pen(Color.Black, 0) i = -2

For x As Integer = 0 To x_max For y As Integer = 1 To y_max

i = i + 2

x1 = myArrayVB(i, 0)

y1 = myArrayVB(i, 1)

x2 = myArrayVB(i + 1, 0)

y2 = myArrayVB(i + 1, 1) e.Graphics.DrawLine(myPen, x1, y1, x2, y2)

Глава 30. Изображение и управление поверхностями на VB для VC++, VC# 143

Next Next

'Рисуем линии, параллельные плоскости yz: i = N_1_myArrayVB - 1

For y As Integer = 0 To y_max For x As Integer = 1 To x_max

i = i + 2

x1 = myArrayVB(i, 0)

y1 = myArrayVB(i, 1)

x2 = myArrayVB(i + 1, 0)

y2 = myArrayVB(i + 1, 1) e.Graphics.DrawLine(myPen, x1, y1, x2, y2)

Next Next

'Рисуем три оси координат: i = N_2_myArrayVB - 1

Dim myPen2 As New Pen(Color.Red, 0) For k As Integer = 1 To 3

i = i + 2

x1 = myArrayVB(i, 0)

y1 = myArrayVB(i, 1)

x2 = myArrayVB(i + 1, 0)

y2 = myArrayVB(i + 1, 1) e.Graphics.DrawLine(myPen2, x1, y1, x2, y2)

Next

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

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

Dim sw As StreamWriter = _

New StreamWriter("D:\MyDocs\MyTest.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 Sub

Чтобы мы могли управлять (например, вращать) объектами при помощи нажатия клавиш, в окне Class Name выбираем (Overrides), а в окне Method Name выбираем ProcessCmdKey. Появляется файл Form1.vb с шаблоном (процедуры ProcessCmdKey), который после записи нашего кода принимает следующий вид.

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

Листинг 30.3. Метод ProcessCmdKey для вращения поверхности.

'Поворачиваем поверхность после нажатия клавиши: Protected Overrides Function ProcessCmdKey( _ ByRef msg As System.Windows.Forms.Message, _

ByVal keyData As System.Windows.Forms.Keys) As Boolean 'Задаем шаг поворота поверхности:

Const delta_theta As Double = PI / 32 Const delta_phi As Double = PI / 16

'Вычисляем сферические координаты (spherical coordinates) 'точки наблюдения:

Dim theta As Double = Atan2(myEye.orig_coord(1), _ myEye.orig_coord(0))

Dim r1 As Double = Sqrt(myEye.orig_coord(0) * _ myEye.orig_coord(0) _

+ myEye.orig_coord(1) * myEye.orig_coord(1)) Dim r2 As Double = Sqrt(myEye.orig_coord(0) * _

myEye.orig_coord(0) _ + myEye.orig_coord(1) * myEye.orig_coord(1) + _

myEye.orig_coord(2) * myEye.orig_coord(2))

Dim phi As Double = Atan2(myEye.orig_coord(2), r1) 'Корректируем углы phi и theta:

Select Case keyData Case Keys.Left

theta = theta - delta_theta Case Keys.Up

phi = phi - delta_phi

If phi < -PI / 2 Then phi = -PI / 2 Case Keys.Right

theta = theta + delta_theta Case Keys.Down

phi = phi + delta_phi

If phi > PI / 2 Then phi = PI / 2 Case Else

Exit Function End Select

'Изменяем координаты точки наблюдения: myEye.orig_coord(0) = r1 * Cos(theta) myEye.orig_coord(1) = r1 * Sin(theta) myEye.orig_coord(2) = r2 * Sin(phi) 'Перерисовываем изображение внутри PictureBox1: PictureBox1.Invalidate()

End Function

Ниже этого кода записываем следующий метод.

Глава 30. Изображение и управление поверхностями на VB для VC++, VC# 145

Листинг 30.4. Метод CalculateTransformation.

'Вычисляем матрицу преобразования 'для текущей точки наблюдения:

Private Function CalculateTransformation() As myClassMatrix3D 'Поворачиваем вокруг оси z,

'чтобы точка наблюдения оказалась в плоскости y-z: Dim transformation1 As myClassMatrix3D = _ myClassMatrix3D.GetZRotPointToYZ(myEye) 'Поворачиваем вокруг оси x,

'чтобы точка наблюдения оказалась на оси z: Dim transformation2 As myClassMatrix3D = _ myClassMatrix3D.GetXRotPointToZ(myEye) 'Проецируем по оси z, игнорируя координату z. 'Умножаем матрицы преобразования:

Return transformation1.TimesMatrix(transformation2) End Function

Ниже этого автоматически сгенерированного класса Form1: Public Class Form1

Inherits System.Windows.Forms.Form

End Class

вводим два новых класса с методами преобразования систем координат.

Листинг 30.5. Два новых класса.

'Вводим класс с методами преобразования систем координат 'в трехмерном пространстве:

Public Class myClassPoint3D

'Массив из 4-х элементов для первоначальных координат

'(original coordinates); нулевой индекс используем: Public orig_coord(3) As Double

'Массив для преобразованных координат

'(transformed coordinates): Public trans_coord(3) As Double

'Создаем новый неинициализированный вектор: Public Sub New()

End Sub

'Создаем новый инициализированный вектор:

Public Sub New(ByVal x As Double, ByVal y As Double, _ ByVal z As Double, Optional ByVal myScale As Double = 1)

orig_coord(0) = x orig_coord(1) = y orig_coord(2) = z orig_coord(3) = myScale

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

End Sub

'Матрица преобразования (transformation matrix): Public Function Transformation( _

ByVal matrix As myClassMatrix3D, _

Optional ByVal normalize As Boolean = True) _ As myClassPoint3D

Dim value As Double

Dim result As New myClassPoint3D For i As Integer = 0 To 3

value = 0

For j As Integer = 0 To 3 value = value + _

orig_coord(j) * matrix.M(j, i)

Next

trans_coord(i) = value Next

'Повторно нормализуем точку: If normalize Then

'После выхода из цикла value = trans_coord(3): trans_coord(0) = trans_coord(0) / value trans_coord(1) = trans_coord(1) / value trans_coord(2) = trans_coord(2) / value trans_coord(3) = 1

End If

End Function End Class

'Вводим класс с методами преобразования координат точки 'в трехмерном пространстве:

Public Class myClassMatrix3D

'Матрица (matrix) в виде массива размера 4x4:

Public M(3,

3)

As Double

'Создаем новую неинициализированную матрицу:

Public Sub New()

End Sub

 

 

'Создаем новую инициализированную матрицу:

Public Sub New( _

ByVal m00

As Double, ByVal m01 As Double, _

ByVal m02

As Double, ByVal m03 As Double, _

ByVal m10

As Double, ByVal m11 As Double, _

ByVal m12

As Double, ByVal m13 As Double, _

ByVal m20

As Double, ByVal m21 As Double, _

ByVal m22

As Double, ByVal m23 As Double, _

ByVal m30

As Double, ByVal m31 As Double, _

ByVal m32

As Double, ByVal m33 As Double)

M(0, 0)

= m00 : M(0, 1) = m01 : M(0, 2) = m02

M(0, 3)

= m03

Глава 30. Изображение и управление поверхностями на VB для VC++, VC# 147

M(1, 0) = m10 : M(1, 1) = m11 : M(1, 2) = m12 M(1, 3) = m13

M(2, 0) = m20 : M(2, 1) = m21 : M(2, 2) = m22 M(2, 3) = m23

M(3, 0) = m30 : M(3, 1) = m31 : M(3, 2) = m32 M(3, 3) = m33

End Sub

'Умножение матрицы на матрицу справа: Public Function TimesMatrix( _

ByVal right_matrix As myClassMatrix3D) As myClassMatrix3D Dim result As New myClassMatrix3D

Dim value As Double

For i As Integer = 0 To 3 For j As Integer = 0 To 3

value = 0

For k As Integer = 0 To 3 value = value + M(i, k) * _ right_matrix.M(k, j)

Next

result.M(i, j) = value Next

Next

Return result End Function

'Поворот вокруг оси z до точки в y-z плоскости: Public Shared Function GetZRotPointToYZ( _ ByVal pt As myClassPoint3D) As myClassMatrix3D

Dim R As Double = Sqrt(pt.orig_coord(0) * _ pt.orig_coord(0) + _

pt.orig_coord(1) * pt.orig_coord(1))

Dim stheta As Double = pt.orig_coord(0) / R Dim ctheta As Double = pt.orig_coord(1) / R Return New myClassMatrix3D( _

ctheta, stheta, 0, 0, _ -stheta, ctheta, 0, 0, _ 0, 0, 1, 0, _ 0, 0, 0, 1)

End Function

'Поворот вокруг оси x до точки на оси z: Public Shared Function GetXRotPointToZ( _ ByVal pt As myClassPoint3D) As myClassMatrix3D

Dim R1 As Double = Sqrt(pt.orig_coord(0) * _ pt.orig_coord(0) + pt.orig_coord(1) * _

pt.orig_coord(1))

Dim R2 As Double = Sqrt(pt.orig_coord(0) * _ pt.orig_coord(0) + pt.orig_coord(1) * _

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

pt.orig_coord(1) + pt.orig_coord(2) * _ pt.orig_coord(2))

Dim sphi As Double = -R1 / R1

Dim cphi As Double = -pt.orig_coord(2) / R2 Return New myClassMatrix3D( _

1, 0, 0, 0, _

0, cphi, sphi, 0, _ 0, -sphi, cphi, 0, _ 0, 0, 0, 1)

End Function End Class

Глава 31. Изображение поверхностей в проекте Visual C++ по данным из проекта

Visual C# или Visual Basic

Листинг 31.1. Метод для рисования поверхности.

//Концы числового интервала области задания поверхно-сти: private: static const int x_max = 20;

private: static const int y_max = 20; private: static const int x_min = -10; private: static const int y_min = -10; private: System::Void pictureBox1_Paint( System::Object^ sender,

System::Windows::Forms::PaintEventArgs^ e)

{

//Масштабируем объекты класса Graphics на pictureBox1. //Коэффициенты масштабирования:

float M_1 = 31; float M_2 = 29; e->Graphics->ScaleTransform(

Convert::ToSingle(pictureBox1->Width / M_1),

Convert::ToSingle(-pictureBox1->Height / M_2), MatrixOrder::Append);

float M_3 = 1.9f; float M_4 = 1.7f;

e->Graphics->TranslateTransform( Convert::ToSingle(pictureBox1->Width / M_3), Convert::ToSingle(pictureBox1->Height / M_4), MatrixOrder::Append);

//Задавая M_1, M_2, M_3, M_4 другие значения,

//мы будем смещать пов-ть по отношению к осям x,y,z. //Объявляем индексы элементов массива myArrayVC(i, j): int i, j;

//Значение первой, второй и третьей границ индекса "i": int N_1_myArray, N_2_myArray, N_3_myArray;

//Задаем границы индексов массива myArrayVC(i, j): int N_x = 2001;

int N_y = 2;

//Объявляем массив myArrayVC(i, j) переменных float, //когда i = 0,1,2,3,...,(N_x - 1);

// j = 0,1,2,3,...,(N_y - 1): array<float,2>^ myArrayVC =

gcnew array<float,2>(N_x, N_y);

//Для считывания из файла D:\\MyDocs\\MyTest.txt

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