Жарков В.А. - Visual C++ 2005, DirectX 9.0c и Microsoft Agent в компьютерной графике, мультимедиа и играх (Листинги книги) - 2005
.pdf190 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
//Заполняем вершины данными. //Задаем размеры конуса: float zoom1 = -1;
float zoom2 = -1;
float theta = (float)(2 * Math::PI * i) / 49; //Вращающийся конус с одной неподвижной вершиной. //Рассчитываем координаты вершин:
Vertex[2 * i].Position = Vector3((float)Math::Sin(theta), zoom1, (float)Math::Cos(theta));
//Рассчитываем нормали в вершинах: Vertex[2 * i + 1].Normal =
Vector3((float)Math::Sin(theta), zoom2, (float)Math::Cos(theta));
}
//Разблокируем буфер вершин: myVertexBuffer->Unlock();
}
//Включаем таймер и выполняем матричные преобразования: private: void SetupMatrices()
{
//Используем глобальную матрицу (world matrix), //чтобы вращать фигуру вокруг оси y: myDevice->Transform->World = Matrix::RotationAxis(
Vector3(
(float)Math::Cos(Environment::TickCount / 250.0f), 1,
(float)Math::Sin(Environment::TickCount / 250.0f)), Environment::TickCount / 3000.0f);
//Задаем координаты глаза наблюдателя
//в матрице вида (view matrix): myDevice->Transform->View = Matrix::LookAtLH(
Vector3(0.0f, 3.0f, -5.0f),
Vector3(0.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f));
//При помощи матрицы проецирования (projection matrix) //выполняем перспективные преобразования: myDevice->Transform->Projection =
Matrix::PerspectiveFovLH( (float)Math::PI / 4, 1.0f, 1.0f, 100.0f);
}
//Определяем освещение фигуры цветом формата ARGB: private: void SetupLights()
{
//Устанавливаем материал и его цвет.
//Можно одновременно использовать только один материал: Material myMaterial = Material();
Глава 37. Методика проектирования пространственных фигур |
191 |
Color myColor = Color::White; myMaterial.Diffuse = myColor; myMaterial.Ambient = myColor; myDevice->Material = myMaterial; //Устанавливаем белое освещение //с изменяющимся направлением:
myDevice->Lights[0]->Type = LightType::Directional; myDevice->Lights[0]->Diffuse = Color::DarkTurquoise; myDevice->Lights[0]->Direction = Vector3(
(float)Math::Cos(Environment::TickCount / 250.0f), 1.0f,
(float)Math::Sin(Environment::TickCount / 250.0f)); //Включаем освещение:
myDevice->Lights[0]->Enabled = true; //Включаем немного отраженного (Ambient) //равномерно рассеянного света: myDevice->RenderState->Ambient =
Color::FromArgb(0x202020);
}
//Останавливаем вращение фигуры и изменяем ее размеры //во время изменения размеров формы:
protected: void OnResize(EventArgs^ e)
{
myPause = ((this->WindowState == FormWindowState::Minimized) || !this->Visible);
}
Теперь в файле Form1.cpp находим главный метод Main, комментируем весь имеющийся в этом методе автоматически сгенерированный код и записываем код со следующего листинга (для вывода формы Form1 и рисования на ней графики).
Листинг 37.3. Код для вывода формы и рисования на ней графики.
//В классе Form1 объявляем объект myForm1
//и после знака равентства создаем его экземпляр: Form1^ myForm1 = gcnew Form1();
if (!myForm1->InitializeDirectX())
{
MessageBox::Show("Ошибка при инициализации DirectX."); return 0;
}
//Показываем форму Form1: myForm1->Show();
//Рисуем графику на форме Form1: while (myForm1->Created)
{
myForm1->myRendering();
192 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
Application::DoEvents();
}
return 0;
Листинг 37.4. Методы для визуализации преобразованных вершин фигуры.
//Объявляем и инициализируем глобальные переменные. //Для устройства myDevice класса Device:
static Device^ myDevice = nullptr; //Для буфера вершин VertexBuffer:
static VertexBuffer^ myVertexBuffer = nullptr; static PresentParameters^ myPresentParameters =
gcnew PresentParameters(); static bool myPause = false; //Устанавливаем параметры Direct3D: public: bool InitializeDirectX()
{
try
{
myPresentParameters->Windowed = true; myPresentParameters->SwapEffect =
SwapEffect::Discard; myPresentParameters->EnableAutoDepthStencil = true; myPresentParameters->AutoDepthStencilFormat =
DepthFormat::D16;
//Создаем устройство для визуализации вершин фигуры: myDevice = gcnew Device(0, DeviceType::Hardware,
this, CreateFlags::SoftwareVertexProcessing, myPresentParameters);
myDevice->DeviceReset +=
gcnew System::EventHandler(this->OnResetDevice); //Вызываем разработанные нами методы: this->OnCreateDevice(myDevice, nullptr); this->OnResetDevice(myDevice, nullptr);
myPause = false; return true;
}
catch (DirectXException^)
{
//Перехвачена ошибка инициализации DirectX: return false;
}
}
//Метод для начала и окончания визуализации (rendering) //преобразованных вершин:
public: void myRendering()
{
Глава 37. Методика проектирования пространственных фигур |
193 |
if (myPause) return;
//Задаем белый цвет (Color::White) форме Form1: myDevice->
Clear(ClearFlags::Target | ClearFlags::ZBuffer, System::Drawing::Color::White, 1.0f, 0);
//Начинаем сцену: myDevice->BeginScene(); //Устанавливаем освещение и матерал: SetupLights();
//Используем матрицы для выполнения преобразований: SetupMatrices();
myDevice->SetStreamSource(0, myVertexBuffer, 0); myDevice->VertexFormat =
CustomVertex::PositionNormal::Format; //Рисуем фигуру: myDevice->DrawPrimitives(
PrimitiveType::TriangleStrip, 0, (4 * 25) - 2); //Заканчиваем сцену:
myDevice->EndScene(); //Показываем сцену: myDevice->Present();
}
//Создаем устройство, буфер вершин фигуры и их данные: public: void OnCreateDevice(Object^ sender, EventArgs^ e)
{
Device^ myDev = (Device^)sender; //Создаем буфер для вершин фигуры: myVertexBuffer = gcnew VertexBuffer(
typeid<CustomVertex::PositionNormal>, 100, myDev, Microsoft::DirectX::Direct3D::Usage::WriteOnly, CustomVertex::PositionNormal::Format, Pool::Default);
//Создаем геометрические данные при помощи обработки
//события myVertexBuffer->Created: myVertexBuffer->Created +=
gcnew System::EventHandler( this->OnCreateVertexBuffer);
this->OnCreateVertexBuffer(myVertexBuffer, nullptr);
}
//Настраиваем параметры устройства для рисования: public: static void OnResetDevice(Object^ sender, EventArgs^ e)
{
Device^ myDev = (Device^)sender; //Выключаем режим CullMode, чтобы мы видели //переднюю и заднюю поверхность фигуры: myDev->RenderState->CullMode = Cull::None;
194 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
//Для рисования трехмерной фигуры включаем Z - буфер: myDevice->RenderState->ZBufferEnable = true;
//Делаем доступным освещение: myDevice->RenderState->Lighting = true;
}
//Массив параметров вершин. Строим фигуру в буфере вершин: public: static void OnCreateVertexBuffer(
Object^ sender, EventArgs^ e)
{
//Для фигуры с любым количеством вершин //объявляем массив и выполняем преобразование типов: array<CustomVertex::PositionNormal>^ Vertex =
(array<CustomVertex::PositionNormal>^) myVertexBuffer->Lock(0, Microsoft::DirectX::Direct3D::LockFlags::None);
//В классе (структуре) PositionNormal
//создаем массив из 100 пользовательских вершин: for (int i = 0; i < 50; i++)
{
//Заполняем вершины данными.
//Вращающийся цилиндр с динамичным освещением. //Задаем размеры цилиндра:
float zoom1 = -1.5; float zoom2 = 1.5;
float theta = (float)(2 * Math::PI * i) / 49; //Рассчитываем координаты (Position) и //нормали (Normal) вершин:
Vertex[2 * i].Position = Vector3((float)Math::Sin(theta), zoom1, (float)Math::Cos(theta)); Vertex[2 * i].Normal = Vector3((float)Math::Sin(theta), 0, (float)Math::Cos(theta)); Vertex[2 * i + 1].Position = Vector3((float)Math::Sin(theta), zoom2, (float)Math::Cos(theta)); Vertex[2 * i + 1].Normal = Vector3((float)Math::Sin(theta), 0, (float)Math::Cos(theta));
}
//Разблокируем буфер вершин: myVertexBuffer->Unlock();
}
//Включаем таймер и выполняем матричные преобразования: private: void SetupMatrices()
{
//Используем глобальную матрицу (world matrix),
Глава 37. Методика проектирования пространственных фигур |
195 |
//чтобы вращать фигуру вокруг оси y: myDevice->Transform->World = Matrix::RotationAxis(
Vector3(
(float)Math::Cos(Environment::TickCount / 250.0f), 1,
(float)Math::Sin(Environment::TickCount / 250.0f)), Environment::TickCount / 3000.0f);
//Задаем координаты глаза наблюдателя
//в матрице вида (view matrix): myDevice->Transform->View = Matrix::LookAtLH(
Vector3(0.0f, 3.0f, -5.0f),
Vector3(0.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f));
//При помощи матрицы проецирования (projection matrix) //выполняем перспективные преобразования: myDevice->Transform->Projection =
Matrix::PerspectiveFovLH( (float)Math::PI / 4, 1.0f, 1.0f, 100.0f);
}
//Определяем освещение фигуры цветом формата ARGB: private: void SetupLights()
{
//Устанавливаем материал и его цвет.
//Можно одновременно использовать только один материал: Material myMaterial = Material();
Color myColor = Color::White; myMaterial.Diffuse = myColor; myMaterial.Ambient = myColor; myDevice->Material = myMaterial; //Устанавливаем белое освещение //с изменяющимся направлением:
myDevice->Lights[0]->Type = LightType::Directional; myDevice->Lights[0]->Diffuse = Color::DarkTurquoise; myDevice->Lights[0]->Direction = Vector3(
(float)Math::Cos(Environment::TickCount / 250.0f), 1.0f,
(float)Math::Sin(Environment::TickCount / 250.0f)); //Включаем освещение:
myDevice->Lights[0]->Enabled = true; //Включаем немного отраженного (Ambient) //равномерно рассеянного света: myDevice->RenderState->Ambient =
Color::FromArgb(0x202020);
}
//Останавливаем вращение фигуры и изменяем ее размеры //во время изменения размеров формы:
protected: void OnResize(EventArgs^ e)
196 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
{
myPause = ((this->WindowState == FormWindowState::Minimized) || !this->Visible);
}
Листинг 37.5. Методы для визуализации преобразованных вершин фигуры.
//Объявляем и инициализируем глобальные переменные. //Устройство myDevice класса Device для визуализации вершин: static Device^ myDevice = nullptr;
//Буфер вершин VertexBuffer:
static VertexBuffer^ myVertexBuffer = nullptr; //Объявляем и инициализируем объект myTexture //класса Texture:
static Texture^ myTexture = nullptr;
static PresentParameters^ myPresentParameters = gcnew PresentParameters();
static bool myPause = false; //Устанавливаем параметры Direct3D: public: bool InitializeDirectX()
{
try
{
myPresentParameters->Windowed = true; myPresentParameters->SwapEffect =
SwapEffect::Discard; myPresentParameters->EnableAutoDepthStencil = true; myPresentParameters->AutoDepthStencilFormat =
DepthFormat::D16;
//Создаем устройство для визуализации вершин фигуры: myDevice = gcnew Device(0, DeviceType::Hardware,
this, CreateFlags::SoftwareVertexProcessing, myPresentParameters);
myDevice->DeviceReset +=
gcnew System::EventHandler(this->OnResetDevice); //Вызываем разработанные нами методы: this->OnCreateDevice(myDevice, nullptr); this->OnResetDevice(myDevice, nullptr);
myPause = false; return true;
}
catch (DirectXException^)
{
//Перехвачена ошибка инициализации DirectX: return false;
}
}
Глава 37. Методика проектирования пространственных фигур |
197 |
//Метод для начала и окончания визуализации (rendering) //преобразованных вершин:
public: void myRendering()
{
if (myPause) return;
//Задаем белый цвет (Color::White) форме Form1: myDevice->
Clear(ClearFlags::Target | ClearFlags::ZBuffer, System::Drawing::Color::White, 1.0f, 0);
//Начинаем сцену: myDevice->BeginScene();
//Используем матрицы для выполнения преобразований: SetupMatrices();
//Устанавливаем нашу текстуру: myDevice->SetTexture(0, myTexture); myDevice->TextureState[0]->ColorOperation =
TextureOperation::Modulate; myDevice->TextureState[0]->ColorArgument1 =
TextureArgument::TextureColor; myDevice->TextureState[0]->ColorArgument2 =
TextureArgument::Diffuse; myDevice->TextureState[0]->AlphaOperation =
TextureOperation::Disable; //Рисуем фигуру:
myDevice->SetStreamSource(0, myVertexBuffer, 0); myDevice->VertexFormat =
CustomVertex::PositionNormalTextured::Format; myDevice->DrawPrimitives(
PrimitiveType::TriangleStrip, 0, (4 * 25) - 2); //Заканчиваем сцену:
myDevice->EndScene(); //Показываем сцену: myDevice->Present();
}
//Создаем устройство, буфер вершин фигуры и их данные: public: void OnCreateDevice(Object^ sender, EventArgs^ e)
{
Device^ myDev = (Device^)sender; //Создаем буфер для вершин фигуры: myVertexBuffer = gcnew VertexBuffer(
typeid<CustomVertex::PositionNormalTextured>, 100, myDev, Microsoft::DirectX::Direct3D::Usage::WriteOnly, CustomVertex::PositionNormalTextured::Format, Pool::Default);
//Создаем геометрические данные при помощи обработки
//события myVertexBuffer->Created:
198 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
myVertexBuffer->Created += gcnew System::EventHandler( this->OnCreateVertexBuffer);
this->OnCreateVertexBuffer(myVertexBuffer, nullptr);
}
//Настраиваем параметры устройства для рисования: public: static void OnResetDevice(Object^ sender, EventArgs^ e)
{
Device^ myDev = (Device^)sender; //Выключаем режим CullMode, чтобы мы видели //переднюю и заднюю поверхности фигуры: myDev->RenderState->CullMode = Cull::None; //Выключаем трехмерное освещение: myDev->RenderState->Lighting = false;
//Для рисования трехмерной фигуры включаем Z - буфер: myDevice->RenderState->ZBufferEnable = true; //Загружаем в проект наш рисунок Texture_1: myTexture = TextureLoader::FromFile(myDev,
"D:\\MyDocs\\Texture_1.bmp");
}
//Массив параметров вершин. Строим фигуру в буфере вершин: public: static void OnCreateVertexBuffer(
Object^ sender, EventArgs^ e)
{
//Для фигуры с любым количеством вершин //объявляем массив и выполняем преобразование типов:
array<CustomVertex::PositionNormalTextured>^ Vertex = (array<CustomVertex::PositionNormalTextured>^) myVertexBuffer->Lock(0, Microsoft::DirectX::Direct3D::LockFlags::None);
//В классе (структуре) PositionNormal
//создаем массив из 100 пользовательских вершин: for (int i = 0; i < 50; i++)
{
//Заполняем вершины данными. //Задаем размеры конуса: float zoom1 = 1;
float zoom2 = 0;
float theta = (float)(2 * Math::PI * i) / 49; //Вращающийся конус с одной неподвижной вершиной. //Рассчитываем нормали в вершинах:
Vertex[2 * i].Normal = Vector3((float)Math::Sin(theta), zoom2, (float)Math::Cos(theta));
//Добавляем в вершину v-компоненту текстуры: Vertex[2 * i].Tv = 1.0f;
Глава 37. Методика проектирования пространственных фигур |
199 |
//Рассчитываем координаты вершин: Vertex[2 * i + 1].Position =
Vector3((float)Math::Sin(theta), zoom1, (float)Math::Cos(theta));
//Добавляем в вершину u-компоненту текстуры: Vertex[2 * i + 1].Tu = ((float)i) / (50 - 1);
}
//Открываем буфер вершин: myVertexBuffer->Unlock();
}
//Включаем таймер и выполняем матричные преобразования: private: void SetupMatrices()
{
//Используем глобальную матрицу (world matrix), //чтобы вращать фигуру вокруг оси y: myDevice->Transform->World = Matrix::RotationAxis(
Vector3(
(float)Math::Cos(Environment::TickCount / 250.0f), 1,
(float)Math::Sin(Environment::TickCount / 250.0f)), Environment::TickCount / 1000.0f);
//Задаем координаты глаза наблюдателя
//в матрице вида (view matrix): myDevice->Transform->View = Matrix::LookAtLH(
Vector3(0.0f, 3.0f, -5.0f),
Vector3(0.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f));
//При помощи матрицы проецирования (projection matrix) //выполняем перспективные преобразования: myDevice->Transform->Projection =
Matrix::PerspectiveFovLH( (float)Math::PI / 4, 1.0f, 1.0f, 100.0f);
}
//Останавливаем вращение фигуры и изменяем ее размеры //во время изменения размеров формы:
protected: void OnResize(EventArgs^ e)
{
myPause = ((this->WindowState == FormWindowState::Minimized) || !this->Visible);
}
Листинг 37.6. Методы для визуализации преобразованных вершин фигуры.
//Объявляем и инициализируем глобальные переменные. //Устройство myDevice класса Device для визуализации вершин: static Device^ myDevice = nullptr;
//Буфер вершин VertexBuffer: