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

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

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

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

MatrixIdentity(ref 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(ref 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(ref Rot3, theta); //Комбинируем матрицы: m3MatMultiply(ref M12, ref T, ref R1);

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

}

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

public void MatrixTranslate(ref float[,] M, float Tx, float Ty, float Tz)

{

MatrixIdentity(ref M);

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

}

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

public void MatrixYRotate(ref float[,] M, float theta)

{

MatrixIdentity(ref 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(ref float[] V, ref float[,] M, ref float[] Result)

{

int i, j; float value = 0;

Result = new float[5] { 0, 0, 0, 0, 0 }; for (i = 1; i <= 4; i++)

{

value = 0;

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

121

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 больше, чем от центра проекции, //эта точка будет удалена:

Result[3] = Single.MaxValue;

}

Result[4] = 1;

}

//Применяем матрицу преобразования к точке: public void MatrixApply(ref float[] V,

ref float[,] M, ref 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(ref float[,] Result, ref float[,] A, ref float[,] B)

{

int i, j, k; float value; Result = new float[5, 5]; 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;

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

}

}

}

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

public void m3MatMultiply(ref float[,] Result, ref float[,] A, ref float[,] 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]

+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;

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

+A[3, 3] * B[3, 1];

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

Result[3, 3] = A[3, 1] * B[1, 3] + A[3, 2] * B[2, 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;

}

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

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)

{

e.Graphics.DrawImage(pictureBox1.Image, 0, 0);

}

Глава 27. Изображение объектов в проекте Visual C++ по данным из другого проекта

Visual C++, Visual Basic или Visual C#

На базе нового синтаксиса языка Visual C++ 2005 двухмерный массив с элементами типа значения объявляется и инициализируется так:

int N_x = 201; int N_y = 2; array<float,2>^ myArrayVC =

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

При инициализации двухмерного массива в правой части вместо N_x, N_y мы можем записать конкретные значения верхних границ индексов.

Перед объявлением массива мы должны еще подключить новое пространство имен (в верхней части автоматически сгенерированного пространства имен с именем нашего проекта):

using namespace stdcli::language;

Кроме этого, для использования класса StreamWriter в проекте Visual C++ 2005 мы должны подключить также пространство имен IO:

using namespace System::IO;

Для считывания координат изображения из файла, например, по адресу

D:\\MyDocs\\MyTest3D_Graphics.txt в массив myArrayVC[N_x, N_y] объявляем объ-

ект sr класса StreamReader и при помощи конструктора gcnew (согласно новому синтаксису Visual C++ 2005) создаем экземпляр этого объекта с параметром в виде пути к файлу с координатами изображения:

StreamReader^ sr = gcnew StreamReader( "D:\\MyDocs\\MyTest3D_Graphics.txt");

Листинг 27.1. Метод для рисования геометрических изображений.

private: System::Void pictureBox1_Paint( System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e)

{

//Объявляем индексы элементов всех массивов: int i, j, k;

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

//Объявляем 1-й массив 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\\MyTest3D_Graphics.txt

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

//координат изображения в массив myArrayVC(201, 2) //создаем объект sr класса StreamReader: StreamReader^ sr = gcnew StreamReader(

"D:\\MyDocs\\MyTest3D_Graphics.txt"); //Считываем из файла MyTest3D_Graphics.txt //координаты изображения в массив myArrayVC(201, 2) //при помощи метода ReadLine:

for (i = 0; i <= N_x - 1; i++) for (j = 0; j <= N_y - 1; j++)

myArrayVC[i, j] = Convert::ToSingle(sr->ReadLine());

sr->Close();

//Рисуем первое изображение по координатам из массива. //Объявляем координаты двух точек:

float x1, y1, x2, y2;

//Будем рисовать пером myPen толщиной 3 пикселя: Pen^ myPen = gcnew Pen(Color::Black, 3); //Объявляем переменные для начала N_first_line //и конца N_last_line цикла при рисовании:

int N_first_line, N_last_line;

//Передаем переменным для начала и конца цикла //значения первых двух элементов массива myArrayVC: N_first_line = Convert::ToInt32(myArrayVC[0, 0]); N_last_line = Convert::ToInt32(myArrayVC[0, 1]); //Рисуем изображение, начиная с точки (1,0; 1,1): i = -1;

for (k = N_first_line; k <= N_last_line; k++)

{

i = i + 2;

x1 = myArrayVC[i, 0];

y1 = myArrayVC[i, 1];

x2 = myArrayVC[i + 1, 0];

y2 = myArrayVC[i + 1, 1]; e->Graphics->DrawLine(myPen, x1, y1, x2, y2);

}

//Задаем границы индексов 2-го массива myArrayVC_2(i, j): int N_x_2 = 201; int N_y_2 = 2;

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

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

gcnew array<float,2>(N_x_2, N_y_2); //Для считывания из файла

//по адресу D:\\MyDocs\\MyTest3D_Graphics_2.txt //координат изображения в массив myArrayVC_2(201, 2) //создаем объект sr_2 класса StreamReader: StreamReader^ sr_2 = gcnew StreamReader(

Глава 27. Изображение объектов в проекте VC++ по данным VC++, VB, VC# 125

"D:\\MyDocs\\MyTest3D_Graphics_2.txt"); //Считываем из файла MyTest3D_Graphics_2.txt //координаты изображения в массив myArrayVC_2(201, 2) //при помощи метода ReadLine:

for (i = 0; i <= N_x - 1; i++) for (j = 0; j <= N_y - 1; j++)

myArrayVC_2[i, j] = Convert::ToSingle(sr_2->ReadLine());

sr_2->Close();

//Рисуем второе изображение по координатам из массива. //Будем рисовать пером myPen толщиной 1:

Pen^ myPen_2 = gcnew Pen(Color::Black, 1); //Объявляем переменные для начала N_first_line //и конца N_last_line цикла при рисовании: int N_first_line_2, N_last_line_2;

//Передаем переменным для начала и конца цикла //значения первых двух элементов массива myArrayVC: N_first_line_2 = Convert::ToInt32(myArrayVC_2[0, 0]); N_last_line_2 = Convert::ToInt32(myArrayVC_2[0, 1]);

//Рисуем изображение, начиная с точки (1,0; 1,1): i = -1;

for (k = N_first_line_2; k <= N_last_line_2; k++)

{

i = i + 2;

x1 = myArrayVC_2[i, 0]; y1 = myArrayVC_2[i, 1];

x2 = myArrayVC_2[i + 1, 0];y2 = myArrayVC_2[i + 1, 1]; e->Graphics->DrawLine(myPen_2, x1, y1, x2, y2);

}

}

Глава 28. Изображение объектов в проекте Visual C# по данным из проекта Visual C++, Visual Basic или Visual C#

Листинг 28.1. Метод для рисования геометрических изображений.

private void pictureBox1_Paint(object sender, PaintEventArgs e)

{

//Объявляем индексы элементов всех массивов: int i, j, k;

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

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

// j = 0,1,2,3,...,(N_y - 1): float[,] myArrayVC = new float[N_x, N_y]; //Для считывания из файла

//по адресу D:\\MyDocs\\MyTest3D_Graphics.txt //координат изображения в массив myArrayVC(201, 2) //создаем объект sr класса StreamReader: StreamReader sr =

new StreamReader( @"D:\\MyDocs\\MyTest3D_Graphics.txt");

//Считываем из файла MyTest3D_Graphics.txt //координаты изображения в массив myArrayVC(201, 2) //при помощи метода ReadLine:

for (i = 0; i <= N_x - 1; i++) for (j = 0; j <= N_y - 1; j++)

myArrayVC[i, j] = Convert.ToSingle(sr.ReadLine());

sr.Close();

//Рисуем первое изображение по координатам из массива. //Объявляем координаты двух точек:

float x1, y1, x2, y2;

//Будем рисовать пером myPen толщиной 3: Pen myPen = new Pen(Color.Black, 3);

//Объявляем переменные для начала N_first_line //и конца N_last_line цикла при рисовании: int N_first_line, N_last_line;

//Передаем переменным для начала и конца цикла //значения первых двух элементов массива myArrayVC: N_first_line = Convert.ToInt32(myArrayVC[0, 0]);

Глава 28. Изображение объектов в проекте VC# по данным VC++, VB, VC# 127

N_last_line = Convert.ToInt32(myArrayVC[0, 1]);

//Рисуем изображение, начиная с точки (1,0; 1,1): i = -1;

for (k = N_first_line; k <= N_last_line; k++)

{

i = i + 2;

x1 = myArrayVC[i, 0];

y1 = myArrayVC[i, 1];

x2 = myArrayVC[i + 1, 0];

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

}

//Задаем границы индексов 2-го массива myArrayVC_2(i, j): int N_x_2 = 201;

int N_y_2 = 2;

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

//j = 0,1,2,3,...,(N_y_2 - 1):

float[,] myArrayVC_2 = new float[N_x_2, N_y_2]; //Для считывания из файла

//по адресу D:\\MyDocs\\MyTest3D_Graphics_2.txt //координат изображения в массив myArrayVC_2(201, 2) //создаем объект sr_2 класса StreamReader: StreamReader sr_2 = new StreamReader(

@"D:\\MyDocs\\MyTest3D_Graphics_2.txt");

//Считываем из файла MyTest3D_Graphics_2.txt //координаты изображения в массив myArrayVC_2(201, 2) //при помощи метода ReadLine:

for (i = 0; i <= N_x - 1; i++) for (j = 0; j <= N_y - 1; j++)

myArrayVC_2[i, j] = Convert.ToSingle(sr_2.ReadLine());

sr_2.Close();

//Рисуем второе изображение по координатам из массива. //Будем рисовать пером myPen толщиной 1:

Pen myPen_2 = new Pen(Color.Black, 1); //Объявляем переменные для начала N_first_line //и конца N_last_line цикла при рисовании: int N_first_line_2, N_last_line_2;

//Передаем переменным для начала и конца цикла //значения первых двух элементов массива myArrayVC: N_first_line_2 = Convert.ToInt32(myArrayVC_2[0, 0]); N_last_line_2 = Convert.ToInt32(myArrayVC_2[0, 1]);

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

//Рисуем изображение, начиная с точки (1,0; 1,1): i = -1;

//for (k = 1; k <= 3; k++)

for (k = N_first_line_2; k <= N_last_line_2; k++)

{

i = i + 2;

x1 = myArrayVC_2[i, 0];

y1 = myArrayVC_2[i, 1];

x2 = myArrayVC_2[i + 1, 0];

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

}

}

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

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

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

//Вводим функцию для изображаемой поверхности z = f(x, y): double f1;

double f(double x, double y)

{

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

double b = 1.02; double c = 1.01;

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

y * y / (b * b)));

return f1;

}

//Точка наблюдения:

myClassPoint3D myEye = new myClassPoint3D();

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

const int y_max = 20; const int x_min = -10; const int y_min = -10; //Массив узловых точек:

myClassPoint3D[,] Points = new myClassPoint3D[x_max + 1, y_max + 1];

//Точки на осях координат:

myClassPoint3D[] Axes = new myClassPoint3D[4];

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

private void Form1_Load(object sender, EventArgs e)

{

//Задаем координаты точки наблюдения: myEye = new myClassPoint3D(40, 20, 20);

//Объявляем координаты точки: double x, y, z; int i, j;

//В каждом (i,j)-м узле плоскости x,y

//рассчитываем координату z точки пов-ти z = f(x, y):

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