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

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

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

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

for (i = 0; i <= x_max; i++)

{

x = i + x_min;

for (j = 0; j <= y_max; j++)

{

y = j + y_min;

//Координата z точек пов-ти z = f(x, y): z = f(x, y);

Points[i, j] = new myClassPoint3D(x, y, z);

}

}

//Инициализация осей (axes) координат: Axes[0] = new myClassPoint3D(0, 0, 0); Axes[1] = new myClassPoint3D(30, 0, 0); Axes[2] = new myClassPoint3D(0, 30, 0); Axes[3] = new myClassPoint3D(0, 0, 30);

}

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

private void pictureBox1_Paint(object sender, PaintEventArgs e)

{

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

float M_1 = 29; float M_2 = 31; e.Graphics.ScaleTransform(pictureBox1.Width / M_1, -pictureBox1.Height / M_2, MatrixOrder.Append); float M_3 = 2; float M_4 = 2;

e.Graphics.TranslateTransform(pictureBox1.Width / M_3, pictureBox1.Height / M_4, MatrixOrder.Append); //Задавая M_1, M_2, M_3, M_4 другие значения,

//мы будем смещать поверхность по отношению к осям x,y,z. //Матрица преобразования (transformation matrix): myClassMatrix3D tr = CalculateTransformation(); //Применяем матрицу преобразования к точкам:

for (int x = 0; x <= x_max; x++) for (int y = 0; y <= y_max; y++)

Points[x, y].Transformation(tr); //Объявляем индексы массива myArrayVCsharp[i, j]: int i, j;

//Задаем границы индексов массива myArrayVCsharp[i, j]: int N_x = 2000; int N_y = 1;

//Задаем массив myArrayVCsharp[i, j]переменных Single, //когда i = 0,1,2,3,...,N_x; j = 0,1,2,3,...,N_y: float[,] myArrayVCsharp = new float[N_x + 1, N_y + 1];

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

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

int N_1_myArrayCsharp = 0, N_2_myArrayCsharp = 0, N_3_myArrayCsharp = 0;

//Рассчитываем элементы массива myArrayVCsharp[i, j] //для рисования линий поверхности,

//параллельных плоскости координат xz: float x1, y1, x2, y2;

Pen myPen = new Pen(Color.Black, 0); i = -2;//Задаем до циклов.

for (int x = 0; x <= x_max; x++)

{

x2 =

Convert.ToSingle(Points[x, 0].trans_coord[0]); y2 =

Convert.ToSingle(Points[x, 0].trans_coord[1]); for (int y = 1; y <= y_max; y++)

{

x1 = x2; y1 = y2;

x2 =

Convert.ToSingle(Points[x, y].trans_coord[0]); y2 =

Convert.ToSingle(Points[x, y].trans_coord[1]); //Можно рисовать линии поверхности и здесь:

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

i = i + 2; myArrayVCsharp[i, 0] = x1; myArrayVCsharp[i, 1] = y1;

myArrayVCsharp[i + 1, 0] = x2; myArrayVCsharp[i + 1, 1] = y2;

N_1_myArrayCsharp = i + 1; //1-я гран. в массиве.

}

}

//Рассчитываем элементы массива myArrayVCsharp[i, j] //для рисования линий поверхности,

//параллельных плоскости координат yz: i = N_1_myArrayCsharp - 1;

for (int y = 0; y <= y_max; y++)

{

x2 =

Convert.ToSingle(Points[0, y].trans_coord[0]); y2 =

Convert.ToSingle(Points[0, y].trans_coord[1]); for (int x = 1; x <= x_max; x++)

{

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

x1 = x2; y1 = y2;

x2 =

Convert.ToSingle(Points[x, y].trans_coord[0]); y2 =

Convert.ToSingle(Points[x, y].trans_coord[1]); //Можно рисовать линии поверхности и здесь: //e.Graphics.DrawLine(myPen,x1,y1, x2, y2); //Записываем в массив координат:

i = i + 2; myArrayVCsharp[i, 0] = x1; myArrayVCsharp[i, 1] = y1;

myArrayVCsharp[i + 1, 0] = x2; myArrayVCsharp[i + 1, 1] = y2;

N_2_myArrayCsharp = i + 1; //2-я гран. в массиве.

}

}

//Преобразовываем оси(axes): for (int k = 0; k <= 3; k++)

Axes[k].Transformation(tr);

//Рассчитываем элементы массива для рисования осей: Pen myPenAxes = new Pen(Color.Red, 0);

i = N_2_myArrayCsharp - 1;

x1 = Convert.ToSingle(Axes[0].trans_coord[0]);

y1 = Convert.ToSingle(Axes[0].trans_coord[1]); for (int k = 1; k <= 3; k++)

{

x2 = Convert.ToSingle(Axes[k].trans_coord[0]);

y2 = Convert.ToSingle(Axes[k].trans_coord[1]); //Можно рисовать оси координат и здесь: //e.Graphics.DrawLine(myPenAxes, x1, y1, x2, y2); //Записываем в массив координат:

i = i + 2; myArrayVCsharp[i, 0] = x1; myArrayVCsharp[i, 1] = y1;

myArrayVCsharp[i + 1, 0] = x2; myArrayVCsharp[i + 1, 1] = y2;

N_3_myArrayCsharp = i + 1; //Число чисел в массиве.

}

//Рисуем при помощи массива

//координат myArrayVCsharp[2000, 1]. //Рисуем линии, параллельные плоскости xz: i = -2;

for (int x = 0; x <= x_max; x++)

{

for (int y = 1; y <= y_max; y++)

{

i = i + 2;

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

x1 = myArrayVCsharp[i, 0];

y1 = myArrayVCsharp[i, 1];

x2 = myArrayVCsharp[i + 1, 0];

y2 = myArrayVCsharp[i + 1, 1]; e.Graphics.DrawLine(myPen, x1, y1, x2, y2);

}

}

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

for (int y = 0; y <= y_max; y++)

{

for (int x = 1; x <= x_max; x++)

{

i = i + 2;

x1 = myArrayVCsharp[i, 0];

y1 = myArrayVCsharp[i, 1];

x2 = myArrayVCsharp[i + 1, 0];

y2 = myArrayVCsharp[i + 1, 1]; e.Graphics.DrawLine(myPen, x1, y1, x2, y2);

}

}

//Рисуем три оси координат: i = N_2_myArrayCsharp - 1;

Pen myPen2 = new Pen(Color.Red, 0); for (int k = 1; k <= 3; k++)

{

i = i + 2;

x1 = myArrayVCsharp[i, 0];

y1 = myArrayVCsharp[i, 1];

x2 = myArrayVCsharp[i + 1, 0];

y2 = myArrayVCsharp[i + 1, 1]; e.Graphics.DrawLine(myPen2, x1, y1, x2, y2);

}

//Записываем массив myArrayVCsharp[2000, 2] в файл. //Создаем объект sw класса StreamWriter

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

StreamWriter sw =

new StreamWriter("D:\\MyDocs\\MyTest.txt"); //Каждый элемент myArrayVCsharp[i, j] записываем в файл //в виде отдельной строки при помощи процедуры WriteLine: for (i = 0; i <= N_x; i++)

for (j = 0; j <= N_y; j++) sw.WriteLine(myArrayVCsharp[i, j]);

sw.Close();

}//Конец метода pictureBox1_Paint.

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

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

protected override bool ProcessCmdKey(

ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)

{

//Задаем шаг поворота поверхности: const double delta_theta = Math.PI / 32; const double delta_phi = Math.PI / 16;

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

double theta = Math.Atan2(myEye.orig_coord[1], myEye.orig_coord[0]);

double r1 = Math.Sqrt(myEye.orig_coord[0] * myEye.orig_coord[0]

+ myEye.orig_coord[1] * myEye.orig_coord[1]); double r2 = Math.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]); double phi = Math.Atan2(myEye.orig_coord[2], r1); //Корректируем углы phi и theta:

switch (keyData)

{

case Keys.Left:

theta = theta - delta_theta; break;

case Keys.Up:

phi = phi - delta_phi;

if (phi < -Math.PI / 2) phi = -Math.PI / 2; break;

case Keys.Right:

theta = theta + delta_theta; break;

case Keys.Down:

phi = phi + delta_phi;

if (phi > Math.PI / 2) phi = Math.PI / 2; break;

}

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

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

return true;

}

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

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

//Метод для вычисления матрицы преобразования //для текущей точки наблюдения: myClassMatrix3D CalculateTransformation()

{

//Поворачиваем вокруг оси z,

//чтобы точка наблюдения оказалась в плоскости y-z: myClassMatrix3D transformation1 =

myClassMatrix3D.GetZRotPointToYZ(myEye); //Поворачиваем вокруг оси x,

//чтобы точка наблюдения оказалась на оси z: myClassMatrix3D transformation2 =

myClassMatrix3D.GetXRotPointToZ(myEye); //Проецируем по оси z, игнорируя координату z. //Для этого умножаем матрицы преобразования:

return (transformation1.TimesMatrix(transformation2));

}

Ниже этого автоматически сгенерированного класса Form1: public partial class Form1 : System.Windows.Forms.Form

{

}

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

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

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

public class myClassPoint3D

{

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

//(original coordinates); нулевой индекс используем: public double[] orig_coord = new double[4];

//Массив для преобразованных координат: public double[] trans_coord = new double[4];

//Создаем неинициализирующий конструктор этого класса: public myClassPoint3D()

{

}

//Создаем инициализирующий конструктор:

public myClassPoint3D(double x, double y, double z)

{

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

orig_coord[0] = x; orig_coord[1] = y; orig_coord[2] = z; double myScale;

myScale = 1; //Масштаб. orig_coord[3] = myScale;

}

//Матрица преобразования (transformation matrix): bool normalize = true;

public void Transformation(myClassMatrix3D matrix)

{

double value = 0;

myClassPoint3D result = new myClassPoint3D(); int i, j;

for (i = 0; i <= 3; i++)

{

value = 0;

for (j = 0; j <= 3; j++)

value = value + orig_coord[j] * matrix.M[j, i]; trans_coord[i] = value;

}

//Повторно нормализуем точку: if (normalize == true)

{

//После выхода из цикла value = trans_coord[4]: 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;

}

}

} //Конец класса public class myClassPoint3D.

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

public class myClassMatrix3D

{

//Матрица (matrix) в виде массива размера 4x4: public double[,] M = new double[4, 4];

//Создаем неинициализирующий конструктор этого класса: public myClassMatrix3D()

{

}

//Создаем конструктор, инициализирующий матрицу: public myClassMatrix3D(

double m00, double m01, double m02, double m03, double m10, double m11, double m12, double m13,

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

double m20, double m21, double m22, double m23, double m30, double m31, double m32, double m33)

{

M[0, 0] = m00; M[0, 2] = m02; M[1, 0] = m10; M[1, 2] = m12; M[2, 0] = m20; M[2, 2] = m22; M[3, 0] = m30; M[3, 2] = m32;

M[0, 1] = m01; M[0, 3] = m03; M[1, 1] = m11; M[1, 3] = m13; M[2, 1] = m21; M[2, 3] = m23; M[3, 1] = m31; M[3, 3] = m33;

}

//Метод для умножения матрицы на матрицу справа: public myClassMatrix3D TimesMatrix(

myClassMatrix3D right_matrix)

{

myClassMatrix3D result = new myClassMatrix3D(); double value; int i, j, k;

for (i = 0; i <= 3; i++)

{

for (j = 0; j <= 3; j++)

{

value = 0;

for (k = 0; k <= 3; k++)

{

value = value + M[i, k] * right_matrix.M[k, j];

}

result.M[i, j] = value;

}

}

return result;

}

//Метод для поворота вокруг оси z //до точки в y-z плоскости:

public static myClassMatrix3D GetZRotPointToYZ( myClassPoint3D pt)

{

double R = Math.Sqrt(

pt.orig_coord[0] * pt.orig_coord[0] + pt.orig_coord[1] * pt.orig_coord[1]);

double stheta = pt.orig_coord[0] / R; double ctheta = pt.orig_coord[1] / R; return new myClassMatrix3D(

ctheta, stheta, 0, 0, -stheta, ctheta, 0, 0, 0, 0, 1, 0,

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

0, 0, 0, 1);

}

//Метод для поворота вокруг оси x до точки на оси z: public static myClassMatrix3D GetXRotPointToZ(myClassPoint3D pt)

{

double R1 = Math.Sqrt(

pt.orig_coord[0] * pt.orig_coord[0] + pt.orig_coord[1] * pt.orig_coord[1]);

double R2 = Math.Sqrt(

pt.orig_coord[0] * pt.orig_coord[0] + pt.orig_coord[1] * pt.orig_coord[1] + pt.orig_coord[2] * pt.orig_coord[2]);

double sphi = -R1 / R1;

double cphi = -pt.orig_coord[2] / R2; return new myClassMatrix3D(

1, 0, 0, 0,

0, cphi, sphi, 0, 0, -sphi, cphi, 0, 0, 0, 0, 1);

}

} //Конец класса class myClassMatrix3D.

Глава 30. Изображение и управление поверхностями в трехмерном пространстве на

Visual Basic для интеграции с Visual C++, Visual C# и другими языками

Листинг 30.1. Код выше и в теле процедуры Form1_Load.

'Вводим функцию для изображаемой поверхности z = f(x, y): Public Function f(ByVal x As Double, ByVal y As Double) _ As Double

'Параметры поверхности z = f(x, y)для эллипсоида: Dim a As Double = 1.03

Dim b As Double = 1.02

Dim c As Double = 1.01

'Уравнение поверхности z = f(x, y) в виде эллипсоида: f = Sqrt(c * c * (200 - x * x / (a * a) - _

y * y / (b * b)))

End Function 'Точка наблюдения:

Private myEye As myClassPoint3D

'Концы числового интервала области задания поверхности: Private Const x_max As Integer = 20

Private Const y_max As Integer = 20

Private Const x_min As Integer = -10

Private Const y_min As Integer = -10 'Массив узловых точек:

Private Points(x_max, y_max) As myClassPoint3D 'Точки на осях координат:

Private Axes(3) As myClassPoint3D

'Загрузка данных и их инициализация:

Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As EventArgs) Handles MyBase.Load

'Задаем координаты точки наблюдения: myEye = New myClassPoint3D(40, 20, 20) 'Объявляем координаты точки:

Dim x, y, z As Double : Dim i, j As Integer 'В каждом (i,j)-м узле плоскости x,y

'рассчитываем координату z точки поверхности z = f(x, y): For i = 0 To x_max

x = i + x_min

For j = 0 To y_max

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