Будь умным!


У вас вопросы?
У нас ответы:) SamZan.net

Лабораторна робота 11 Лабораторна робота11.

Работа добавлена на сайт samzan.net:

Поможем написать учебную работу

Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 24.11.2024

  •  

Начало формы

 Previous activity

Конец формы

  •  

Начало формы

                                                                                                                                                            

Конец формы

  •  

Начало формы

Next activity 

Конец формы

  •  Учасники
  •  Новини
  •  Курси
  •  Головна

You are here

  •  Платформа дистанційного навчання ПУЕТ
  •    ОГКГ
  •    Resources
  •    Лабораторна робота 11

 

Лабораторна робота11. Досконаліші технології рендеринга в DіrectХ

Для апроксимації тривимірних об'єктів в Direct3D є наступні примітиви:

  •  Microsoft.DirectX.Direct3D.PrimitiveType.PointList - відображає на екрані об'єкт у вигляді набору точок. Цей тип можна використовувати для малювання індексних примітивів.
  •  Microsoft.DirectX.Direct3D.PrimitiveType.LineList - набір ліній, що сполучають пари вершин. При використанні цього примітиву потрібно мати для з'єднання парне число вершин.
  •  Microsoft.DirectX.Direct3D.PrimitiveType.LineStrip - набір ламаних прямих, що сполучають між собою послідовно всі вершини об'єкту. Повинно бути мінімум дві вершини для з'єднання з використанням цього примітиву.
  •  Microsoft.DirectX.Direct3D.PrimitiveType.TriangleList - Відображає набір трьох вершин як окремий ізольований трикутник. Промальовування невидимої поверхні визначається поточним станом рендера відбору (device.RenderState.CullMode = Cull.None - не приховувати зворотну сторону плоскої фігури)
  •  Microsoft.DirectX.Direct3D.PrimitiveType.TriangleStrip - безперервна трикутна ферма, коли кожен наступний трикутник малюється на базі двох вершин попереднього трикутника і однієї нової вершини. За умовчанням відображаються всі парні трикутники.
  •  Microsoft.DirectX.Direct3D.PrimitiveType.TriangleFan - віяло з трикутників, що мають одну загальну вершину.

При малюванні можна використовувати одні і ті ж дані про вершини для будь-якого з цих типів примітивів. Додаток інтерпретуватиме при кожному малюванні той тип примітиву, що йому повідомлюється.

Завдання 1. Відредагувати проект RenderCube з лабораторної роботи 10

  •  Додати посилання на бібліотечні збірки
    •  System.dll
    •  System.Drawing.dll
    •  System.Windows.Forms.dll
    •  Microsoft.DirectX.dll
    •  Microsoft.DirectX.Direct3D.dll

Завдання 2. Рендерінг різних типів примітивів

  •  У функції SetupCamera() видалити дві останні секції коду, що відповідають за повороти об'єкту і приріст кута повороту, а також оголошення самої змінної-поля angle

private float angle = 0;// Закритий член класу

// Установка камери в сцену

private void SetupCamera()

{

//Створення перспективи

device.Transform.Projection = Matrix.PerspectiveFovLH(

(float)Math.PI / 4, // Точка зору рівна 45 градусів

// Співвідношення формату сторін

(float)this.ClientSize.Width / (float)this.ClientSize.Height,

1.0F, // Ближній план

100.0F); // Дальній план

//Додавання камери

device.Transform.View = Matrix.LookAtLH(

new Vector3(0, 0, 5.0F), // Положення камери

new Vector3(), // Положення об'єкту поточне

new Vector3(0, 1, 0)); // Напрям камери

// Освітлення

device.RenderState.Lighting = false;

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 2.0F

angle / (float)Math.PI);

if (flagRotate)

angle += 0.1F;

}

  •  Видалити з класу Form1 спочатку підписку обробника на подію Click форми, потім обробник Form1_Click(), а також опис непотрібного тепер прапорця flagRotate

public Form1()

{

InitializeComponent();

// Усуваємо мерехтіння вікна при нескінченному перемальовуванні

this.SetStyle(ControlStyles.AllPaintingInWmPaint |

ControlStyles.Opaque, true);

this.Click += new EventHandler(Form1_Click);

}

bool flagRotate = true;

void Form1_Click(object sender, EventArgs e)

{

flagRotate = !flagRotate;

}

  •  Додати в клас оголошення поля-посилання NumberItems на кількість вершин об'єкту, що випадково генерується, який відображатимемо із застосуванням різних примітивів

private Device device = null; // Графічний конвеєр

private VertexBuffer vb = null; // Вершинний буфер

private const int NumberItems = 12; // Кількість вершин об'єкту

Кількість вершин 12 тому, що це число парне, ділиться на 3 (що підходить для примітивів LineList і TriangleList) і не настільки велике, щоб захаращувати малюнок. Оголошення змінної як константи доручає компілятору стежити за тим, щоб випадково де-небудь в коді її не змінити.

  •  Змінити у функції InitializeGraphics() розмірність вершинного буфера, замінивши 36 на NumberItems

public void InitializeGraphics()

{

..................................

// Створити вершинний буфер

vb = new VertexBuffer(typeof(CustomVertex.PositionColored),

NumberItems,

device,

Usage.Dynamic | Usage.WriteOnly,

CustomVertex.PositionColored.Format,

Pool.Default)

..................................

}

Змінимо алгоритм завдання координат вершин і заповнення вершинного буфера у функції vb_Created(). Застосуємо засоби випадкового формування координат вершин і їх кольорів.

  •  Оголосити у складі класу Form1 посилальну змінну-поле на генератор випадкових чисел за рівномірним законом розподілу, а в конструкторі Form1() розмістити код створення і ініціалізації цього генератора випадкових чисел

public Form1()

{

InitializeComponent();

// Усуваємо мерехтіння вікна при нескінченному перемальовуванні

this.SetStyle(ControlStyles.AllPaintingInWmPaint |

ControlStyles.Opaque, true);

// Ініціалізація генератора випадкових чисел

rand = new System.Random();

}

private Device device = null; // Графічний конвеєр

private VertexBuffer vb = null; // Вершинний буфер

private const int NumberItems = 12; // Кількість вершин об'єкту

System.Random rand; // Поле для генератора випадкових чисел

  •  Змінити код створення вершин об'єкту у функції vb_Created()

void vb_Created(object sender, EventArgs e)

{

// Визначити внутрішнє посилання на вершинний буфер

VertexBuffer buffer = (VertexBuffer)sender; // Явне приведення типів

// Створити локальний масив посилань для вершин об'єкту

CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[NumberItems];

// Згенерувати випадково координати і кольори вершин

double factor = 2.5d;// Ваговий коефіцієнт

for (int i = 0; i < NumberItems; i++)

{

float xPos = (float)((rand.NextDouble() - rand.NextDouble()) * factor);

float yPos = (float)((rand.NextDouble() - rand.NextDouble()) * factor);

float zPos = (float)((rand.NextDouble() - rand.NextDouble()) * factor);

verts[i].Position = new Vector3(xPos, yPos, zPos);

verts[i].Color = System.Drawing.Color.FromArgb(rand.Next(256),

rand.Next(256),

rand.Next(256)).ToArgb();

}

// Заповнити вершинний буфер даними трикутників

buffer.SetData(verts, 0, LockFlags.None);

}

Організувати проглядання роботи різних примітивів можна послідовним їх перебором з достатньою затримкою. Саму затримку можна вимірювати як різницю в тимчасових тактах процесора між поточним часом і часом запуску додатку і на цей час відображати об'єкт одним і тим же примітивом. Після завершення чергового циклу перебору всіх примітивів необхідно згенерувати нові параметри вершинного буфера, щоб випадково змінити мальований об'єкт.

  •  Додати клас Form1 оголошення двох нових полів, які для читабельності зручніше розташувати перед функцією OnPaint()

// Прапорецьгенерації вершин перед початком

// кожного нового циклу обходу всіх примітивів.

// Перше заповнення вершинного буфера виконане

// у InitializeGraphics() при запуску додатку

private bool needRecreate = false;

// Захоплення стартового часу в тактах

private static readonly int beginTickCount =

System.Environment.TickCount;

protected override void OnPaint(PaintEventArgs e)

{

........................................

}

Змінна beginTickCount оголошена як статична для того, щоб її дані зберігалися в об'єкті-типі, а не об'єкті-екземплярі, на випадок, якщо буде створено декілька екземплярів класу Form1. Ключове слово readonly робить її доступною "тільки для читання". На відміну від константних змінних, що вимагають негайної ініціалізації при оголошенні, змінні "тільки для читання" допускають відкладену ініціалізацію в конструкторі класу.

  •  У функції OnPaint() замінити виклик бібліотечної функції DrawPrimitives() у секції коду формування сцени і колір фону форми виділеним нижче блоком коду, щоб остаточно функція виглядала так

// Прапорецьгенерації вершин перед початком

// кожного нового циклу обходу всіх примітивів.

// Перше заповнення вершинного буфера виконане

// у InitializeGraphics() при запуску додатку

private bool needRecreate = false;

// Захоплення стартового часу в тактах

private static readonly int beginTickCount =

System.Environment.TickCount;

protected override void OnPaint(PaintEventArgs e)

{

// Очистити кольором клієнтську область форми

device.Clear(ClearFlags.Target,

System.Drawing.Color.White,

1.0F, 0);

// Виклик функції установки камери

SetupCamera();

// Сформувати сцену з урахуванням параметрів

// "положення-нормаль-колір"

device.BeginScene();

// Встановити формат обробки вершин при відображенні

device.VertexFormat = CustomVertex.PositionColored.Format;

// Намалювати трикутник даним з буфера

device.SetStreamSource(0, vb, 0);

const int countTime = 5 * 1000; // Тримати зображення 5 секунд

const int countIndex = 6; // Кількість варіантів показу

int index = ((System.Environment.TickCount - beginTickCount) / countTime)

% countIndex;

switch (index)

{

case 0: // PointList

device.DrawPrimitives(PrimitiveType.PointList, 0, NumberItems);

if (needRecreate) // Виконати тільки при черговому index == 0

{

vb_Created(vb, null);// Згенерувати новий вершинний буфер

needRecreate = false;// Скинути прапор регенерації вершин

}

this.Text = "Несполучені точки вершин";

break;

case 1: // LineList

device.DrawPrimitives(PrimitiveType.LineList, 0, NumberItems / 2);

needRecreate = true;// Приготувати прапорець для генерації вершин

// при index == 0

this.Text = "З'єднання пар вершин лініями";

break;

case 2: // LineStrip

device.DrawPrimitives(PrimitiveType.LineStrip, 0, NumberItems - 1);

this.Text = "З'єднання вершин ламаною";

break;

case 3: // TriangleList

device.DrawPrimitives(PrimitiveType.TriangleList, 0, NumberItems / 3);

this.Text = "Окремі трикутники";

break;

case 4: // TriangleStrip

device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, NumberItems - 2);

this.Text = "Безперервна ферма трикутників";

break;

case 5: // TriangleFan

device.DrawPrimitives(PrimitiveType.TriangleFan, 0, NumberItems - 2);

this.Text = "Трикутне віяло з точки";

break;

}

device.EndScene();

// Показати буфер кадру

device.Present();

// Примусово перемальовувати

this.Invalidate();

}

  •  Додати в кінець функції SetupCamera() код зміни стану рендера для збільшення розміру точок вершин, що відображаються, щоб їх можна було розрізнити в нульовому режиміPointList

// Установка камери в сцену

private void SetupCamera()

{

//Створення перспективи

device.Transform.Projection = Matrix.PerspectiveFovLH(

(float)Math.PI / 4, // Точка зору рівна 45 градусів

// Співвідношення формату сторін

(float)this.ClientSize.Width / (float)this.ClientSize.Height,

1.0F, // Ближній план

100.0F); // Дальній план

//Додавання камери

device.Transform.View = Matrix.LookAtLH(

new Vector3(0, 0, 5.0F), // Положення камери

new Vector3(), // Положення об'єкту поточне

new Vector3(0, 1, 0)); // Напрям камери

// Освітлення

device.RenderState.Lighting = false;

// Збільшення масштабу відображення точок вершин об'єкту

device.RenderState.PointSize = 5.0f;

}

  •  Побудувати додаток і переконайтись, що форма Form1 періодично генерує нові об'єкти і відображає їх різними примітивами

Завдання 4. Використання індексних буферів

Ще раз розглянемо геометрію куба з попередніх робіт.

Ми апроксимували кожну сторону куба двома трикутниками, задаючи координати вершин кожного трикутника. Ці трикутника у вершинах куба мали однакові координати і багато разів повторювалися при описі трикутників. Код був надмірним і достатньо великим.

Для усунення надмірності зручніше у вершинному буфері задавати тільки координати унікальних точок, якими є вершини куба, а для кожного апроксимуючого трикутника указувати три індекси з масиву вершинного буфера. Ми зберігаємо унікальні координати об'єкту "внавал" окремо, а для трикутних примітивів указуємо триадний список індексів цих координат в масиві вершинного буфера. Такий підхід істотно скорочує кількість даних, що зберігаються, і зменшує необхідну пам'ять комп'ютера.

Масив з індексами опорних точок об'єкту, записаних у вершинному буфері, називається індексним буфером. Індекси, що зберігаються в такому буфері, можуть бути 16- або 32-розрядними цілими числами. Давайте використаємо індексний буфер для моделювання трикутника, що обертається.

  •  Додати до поточного проекту форму Form1 з лабораторної роботи №12. Для цього тимчасово переіменувати через панель Solution Explorer файл Form1.cs поточного проекту і в меню Project (при виділеному вузлі проекту в панелі Solution Explorer) виконати команду Add Existing Item
  •  Після копіювання файлу Form1.cs у поточний каталог проекту привласніть йому через панель Solution Explorer ім'я Form2.cs, а тимчасово перейменованому файлу поверніть первинне ім'я Form1.cs
  •  Відкрити файл Form2.cs у режимі коду і замінити всі входження Form1 на Form2, викликавши в редакторові коду вікно заміни комбінацією клавіш CTRL-H

  •  Не закриваючи вікна Find and Replace відкрийте файл Form2.designer.cs і теж заміните в нім всі входження Form1 на Form2
  •  Не закриваючи вікна Find and Replace встановите в нім опцію Look in в значення Current Project і заміните всі входження простору імен RenderCube на RenderBest, виконавши командуReplace All

  •  Простежити за тим, щоб в обох файлах було використано один і той же простір імен, згідно імені поточного проекту (namespace RenderBest)

Тепер потрібно встановити форму Form2 стартовою для можливості її початкового запуску. Для цього:

  •  У панелі Solution Explorer виділіть вузол проекту і клацніть на піктограмі Properties, щоб викликати вікно властивостей проекту

  •  У вкладці Application вікна властивостей проекту встановити опцію Startup object в значення RenderBest.Form2

  •  Запустити проект на виконання, щоб перевірити початкову працездатність Form2
  •  Відкрити файл Form2.cs у режимі View Code і через список Members правої верхньої частини вікна редактора, що розкривається, позиціонуватись на функцію vb_Created() класуForm2
  •  Ввести в тіло функції код визначення вершин куба (8 вершин) відповідно до малюнка

void vb_Created(object sender, EventArgs e)

{

// Визначити внутрішнє посилання на вершинний буфер

VertexBuffer buffer = (VertexBuffer)sender; // Явне приведення типів

// Створити локальний масив структур неперетворених координат

CustomVertex.PositionColored[] verts =

new CustomVertex.PositionColored[8]; // Задати розмірність масиву на 8 вершин

// Задати параметри вершин куба відповідно до малюнка

//

verts[0]= new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Purple.ToArgb());

verts[1]= new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Red.ToArgb());

verts[2]= new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Blue.ToArgb());

verts[3]= new CustomVertex.PositionColored(1.0F, -1.0F, 1.0F, Color.Yellow.ToArgb());

verts[4]= new CustomVertex.PositionColored(-1.0F, 1.0F, -1.0F, Color.Gold.ToArgb());

verts[5]= new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Green.ToArgb());

verts[6]= new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Black.ToArgb());

verts[7]= new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.WhiteSmoke.ToArgb());

// Заповнити вершинний буфер даними трикутників

buffer.SetData(verts, 0, LockFlags.None);

}

Ми істотно зменшили код створення вершинного буфера, залишивши тільки координати, необхідні для визначення вершин куба. До того ж, для кожної вершини куба ми задали окремий колір.

  •  Знайти у функції InitializeGraphics() секцію створення вершинного буфера і змінити його розмірність з 36 на 8 (у нашого куба 8 вершин)

// Створити вершинний буфер

vb = new VertexBuffer(typeof(CustomVertex.PositionColored),8,device,Usage.Dynamic | Usage.WriteOnly,CustomVertex.PositionColored.Format,

Pool.Default);

  •  Додайти в клас Form2 поле для індексного масиву 16-розрядних цілих чисел (тип short або Int16)

// Визначення індексного масиву вершин трикутних примітивів

private static readonly short[] indices = {

2,0,1,// Задня грань: трикутник 2-0-1 (невидима сторона - обхід лівий)

2,1,3,// Задня грань: трикутник 2-1-3 (невидима сторона - обхід лівий)

5,6,4,// Передня грань: трикутник 5-6-4 (лицьова сторона - обхід правий)

5,7,6,// Передня грань: трикутник 5-7-6 (лицьова сторона - обхід правий)

0,5,4,// Верхня грань: трикутник 0-5-4 (лицьова сторона - обхід правий)

0,2,5,// Верхня грань: трикутник 0-2-5 (лицьова сторона - обхід правий)

1,6,7,// Нижня грань: трикутник 1-6-7 (невидима сторона - обхід лівий)

1,7,3,// Нижня грань: трикутник 1-7-3 (невидима сторона - обхід лівий)

0,6,1,// Ліва грань: трикутник 0-6-1 (невидима сторона - обхід лівий)

0,4,6,// Ліва грань: трикутник 0-4-6 (невидима сторона - обхід лівий)

2,3,7,// Права грань: трикутник 2-3-7 (лицьова сторона - обхід правий)

2,7,5 // Права грань: трикутник 2-7-5 (лицьова сторона - обхід правий)

};

  •  У класі Form2 оголосити поле типу Microsoft.DirectX.Direct3D.IndexBuffer з ім'енем ib для зберігання посилання на індексний буфер. Її зручніше розмістити поряд з посиланням на вершинний буфер

private Device device = null;

private VertexBuffer vb = null;

private IndexBuffer ib = null;

public void InitializeGraphics()

{

.....................

}

Тепер необхідно створити сам індексний буфер, куди можна буде передати для зберігання і використання індекси координат вершинного буфера. Індексний буфер має властивість скидатися також, як вершинний, тому необхідно передбачити обробник відновлення індексного буфера для події Created, а також примусовий виклик цього обробник при першому запуску форми.

  •  Розмістити в самому кінці функції InitializeGraphics() (після коду створення вершинного буфера) код створення індексного буфера і підписку на подію Created. Підписку на подіюCreated виконати вручну, щоб оболонка правильно створила заготовку обробника

public void InitializeGraphics()

{

// Створення об'єкту і настройка параметрів представлення

// Створити об'єкт параметрів представлення

PresentParameters presentParams = new PresentParameters();

// Встановити віконний режим

presentParams.Windowed = true;

// Скидати вміст буфера, якщо він не готовий до представлення

presentParams.SwapEffect = SwapEffect.Discard;

// Створити об'єкт пристрою і зберегти посилання на нього

device = new Device(0, DeviceType.Hardware, this,CreateFlags.SoftwareVertexProcessing, presentParams);

// Перехоплення події зміни форми для скидання пристрою

// Створити вершинний буфер

vb = new VertexBuffer(typeof(CustomVertex.PositionColored), 8, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format,

Pool.Default);

// Реєстрація події Created вершинного буфера

vb.Created += new EventHandler(vb_Created);

// Створити індексний буфер для координат вершин куба

ib = new IndexBuffer(typeof(short),indices.Length,device,

Usage.WriteOnly,

Pool.Default);

// Реєстрація події Created індексного буфера

// Код написати уручну (для створення обробника)!!!

ib.Created += new EventHandler(ib_Created);

// Примусовий виклик обробника при першому запуску

ib_Created(ib, null);

}

  •  Код обробник заповнення індексного буфера після скидання буде таким

// Обробник події повторного заповнення індексного буфера

void ib_Created(object sender, EventArgs e)

{

IndexBuffer buffer = (IndexBuffer)sender;

buffer.SetData(indices, 0, LockFlags.None);

}

Тепер необхідно зареєструвати індексний буфер в пристрої device, щоб функція малювання об'єкту використовувала його.

  •  Встановити у функції SetupCamera() нову величину приросту кута, що визначає меншу швидкість обертання куба

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 2.0F,

angle / (float)Math.PI);

if (flagRotate)

angle += 0.02F;

  •  У функції OnPaint() знайти секцію коду "Сформувати сцену" і внесіти до неї реєстрацію індексного буфера в пристрої і виклик функції DrawIndexedPrimitives(), яка при малюванні використовує індексний буфер

// Сформувати сцену з урахуванням параметрів

// "положення-нормаль-колір"

device.BeginScene();

// Встановити формат обробки вершин при відображенні

device.VertexFormat = CustomVertex.PositionColored.Format;

// Намалювати трикутник даним з буфера

device.SetStreamSource(0, vb, 0);

device.Indices = ib;

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.EndScene();

Функція малювання, яку ми використовували, має наступний синтаксис

public void DrawIndexedPrimitives(

Microsoft.DirectX.Direct3D.PrimitiveType primitiveType, // Чим малюємо

System.Int32 baseVertex, // Зсув від початок буфера до індексу першої вершини

System.Int32 minVertexIndex, // Мінімальний індекс вершини в поточному виклику

System.Int32 numVertices, // Число вершин, використовуваних в поточному виклику

System.Int32 startIndex, // Стартовий індекс для прочитування і відображення

System.Int32 primCount) // Число примітивів, що відображаються

  •  Побудувати додаток і отримати куб, що обертається, з барвистими градієнтами кольорів на гранях

Тут ми не зможемо зробити кожну окрему грань одноколірною, оскільки колір примітиву береться з параметрів вершини, а у нас задані кольори вершин куба, до яких примикають відразу декілька примітивів різних граней.

Завдання 5. Створення декількох кубів, що обертаються, із застосуванням буфера глибини

Буфер глибини (depth buffer, Z-буфер, W-буфер) застосовується в додатках Direct3D для зберігання інформації про глибину об'єкту, що відображається. Ця інформація використовується в процесі растеризування (з векторної в растрову) для визначення того, наскільки піксели перекривають один одного. На даному етапі наше застосування не має буфера глибини, але в цьому розділі ми його введемо і використаємо.

  •  Через контекстне меню панелі Solution Explorer отримати копію файлу Form2 і перейменувати її в Form3.cs
  •  Через контекстне меню панелі Solution Explorer відкрити файл Form3.cs у режимі View Code
  •  У панелі Solution Explorer подвійним клацанням на файлі Form3.designer.cs відкрити його в робочій області редактора оболонки
  •  Прослідкуати, щоб відкритими були тільки файли Form3.cs Form3.designer.cs і замінити в них всі входження Form2 на Form3 через вікно заміни, яке можна викликати комбінацією клавіш CTRL-H. Заздалегідь побудувати опції вікна заміни згідно наступному малюнку

  •  Виконати команду меню Project/RenderBest Properties і встановити форму Form3 стартовою


Запустити проект на виконання і переконаєтись, що
 Form3 працює в колишньому варіанті Form2, тобто цілісність коду збереглася

Спочатку замість одного куба створимо 9 кубів і для правильного їх відображення відсунемо камеру.

  •  Додати в клас Form3 нову функцію DrawCubes() для малювання 9 кубів

private void DrawCubes()

{

//

// Середній ряд

//

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 2.0f,angle / (float)Math.PI / 4.0f) *

Matrix.Translation(0.0f, 0.0f, 0.0f); // По центру

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI / 2.0f, angle / (float)Math.PI * 4.0f) *

Matrix.Translation(4.0f, 0.0f, 0.0f); // Зрушення управо

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 4.0f,angle / (float)Math.PI / 2.0f)

Matrix.Translation(-4.0f, 0.0f, 0.0f); // Зрушення вліво

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

//

// Нижній ряд

//

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 2.0f,angle / (float)Math.PI / 4.0f) *

Matrix.Translation(0.0f, -4.0f, 0.0f); // По центру

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI / 2.0f,angle / (float)Math.PI * 4.0f) *

Matrix.Translation(4.0f, -4.0f, 0.0f); // Зрушення управо

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 4.0f,angle / (float)Math.PI / 2.0f) *

Matrix.Translation(-4.0f, -4.0f, 0.0f); // Зрушення вліво

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

//

// Верхній ряд

//

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 2.0f,angle / (float)Math.PI / 4.0f) *

Matrix.Translation(0.0f, 4.0f, 0.0f); // По центру

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI / 2.0f, angle / (float)Math.PI * 4.0f) *

Matrix.Translation(4.0f, 4.0f, 0.0f); // Зрушення управо

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 4.0f, angle / (float)Math.PI / 2.0f) *

Matrix.Translation(-4.0f, 4.0f, 0.0f); // Зрушення вліво

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

if (flagRotate)

angle += 0.02F;

}

  •  Видалити з функції SetupCamera() дві останні секції, відповідальні за обертання куба, оскільки цю функціональність ми включили в нову функцію DrawCubes()

// Установка камери в сцену

private void SetupCamera()

{

//Створення перспективи

device.Transform.Projection = Matrix.PerspectiveFovLH(

(float)Math.PI / 4, // Точка зору рівна 45 градусів

// Співвідношення формату сторін

(float)this.ClientSize.Width / (float)this.ClientSize.Height,

1.0F, // Ближній план

100.0F); // Дальній план

//Додавання камери

device.Transform.View = Matrix.LookAtLH(

new Vector3(0, 0, 5.0F), // Положення камери

new Vector3(), // Положення об'єкту поточне

new Vector3(0, 1, 0)); // Напрям камери

// Освітлення

device.RenderState.Lighting = false;

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 2.0F

angle / (float)Math.PI);

if (flagRotate)

angle += 0.02F;

}

  •  Замінити в секції формування сцени функції OnPaint() виклик функції DrawIndexedPrimitives() на виклик функції DrawCubes()

// Сформувати сцену з урахуванням параметрів

// "положення-нормаль-колір"

device.BeginScene();

// Встановити формат обробки вершин при відображенні

device.VertexFormat = CustomVertex.PositionColored.Format;

// Намалювати трикутник даним з буфера

device.SetStreamSource(0, vb, 0);

device.Indices = ib;

DrawCubes();

device.EndScene();

  •  У функції SetupCamera() відсунути камеру, щоб була видна вся сцена з 9 кубами

// Установка камери в сцену

private void SetupCamera()

{

//Створення перспективи

device.Transform.Projection = Matrix.PerspectiveFovLH(

(float)Math.PI / 4, // Точка зору рівна 45 градусів

// Співвідношення формату сторін

(float)this.ClientSize.Width / (float)this.ClientSize.Height,

1.0F, // Ближній план

100.0F); // Дальній план

//Додавання камери

device.Transform.View = Matrix.LookAtLH(

new Vector3(0, 0, 15.0F), // Положення камери

new Vector3(), // Положення об'єкту поточне

new Vector3(0, 1, 0)); // Напрям камери

// Освітлення

device.RenderState.Lighting = false;

}

  •  Запустити додаток і отримати

  •  Додайти в кінець функції DrawCubes() код для малювання ще трьох кубів

private void DrawCubes()

{

//

// Середній ряд

//

//.................................................

//

// Додаткові куби

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 2.0f,angle / (float)Math.PI / 4.0f) *

Matrix.Translation(0.0f,(float)Math.Cos(angle),(float)Math.Sin(angle));

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,angle / (float)Math.PI / 2.0f,

angle / (float)Math.PI * 4.0f) *

Matrix.Translation(4.0f,

(float)Math.Sin(angle),

(float)Math.Cos(angle));

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

device.Transform.World = Matrix.RotationYawPitchRoll(

angle / (float)Math.PI,

angle / (float)Math.PI * 2.0f,

angle / (float)Math.PI / 2.0f) *

Matrix.Translation(

-4.0f,

(float)Math.Cos(angle),

(float)Math.Sin(angle));

device.DrawIndexedPrimitives(

PrimitiveType.TriangleList, 0, 0, 8, 0, indices.Length / 3);

if (flagRotate)

angle += 0.02F;

}

  •  Запустити додаток і побачити по горизонтальному середньому ряду ще додаткових три куби

Тут ми хочемо отримати обертання додаткових кубів навколо трьох центральних кубів, розташованих по горизонталі. Щоб цього досягти, слід додати буфер глибини в пристрій device.

Існують різні формати буферів глибини, але більшість сучасних графічних плат підтримують 16-розрядні буфери глибини. Тому використовуємо саме таку глибину.

  •  Додатиу функцію InitializeGraphics() перед кодом створення пристрою параметри настройки буфера глибини

public void InitializeGraphics()

{

// Створення об'єкту і настройка параметрів представлення

// Створити об'єкт параметрів представлення

PresentParameters presentParams = new PresentParameters();

// Встановити віконний режим

presentParams.Windowed = true;

// Скидати вміст буфера, якщо він не готовий до представлення

presentParams.SwapEffect = SwapEffect.Discard;

// Настройка буфера глибини для параметрів пристрою

presentParams.EnableAutoDepthStencil = true;

presentParams.AutoDepthStencilFormat =

Microsoft.DirectX.Direct3D.DepthFormat.D16;

// Створити об'єкт пристрою і зберегти посилання на нього

device = new Device(0, DeviceType.Hardware, this,

CreateFlags.SoftwareVertexProcessing, presentParams);

// Створити вершинний буфер

// .................................................

}

  •  Запустити додаток і побачити, що замість кубів з'явилися їх осколки

Зникнення сцени після додавання параметрів буфера глибини відбулося тому, що цей буфер не був очищений

  •  Додати до першої секції коду функції OnPaint() додатковий прапорець очищення буфера глибини

protected override void OnPaint(PaintEventArgs e)

{

// Очистити кольором клієнтську область форми

device.Clear(ClearFlags.Target

| ClearFlags.ZBuffer,

System.Drawing.Color.CornflowerBlue,

1.0F, 0);

..........................................

}

  •  Запустите додаток і побачити ілюструцацію використання буфера глибини

Last modified: Tuesday, 1 November 2011, 10:14 AM

You are logged in as student7 student7 (Logout)




1. Crime privte ~ это не только классически изящный криминальный роман но и вечный поединок страсти и рассудка ре
2. Ставлення до подій- мужність чи боягузство принциповість чи безпринципність оптимізм чи песимізм; 2
3. Введение 3 Сущность конкурентоспособности предприятия 4 Основные с
4. Безопасность www-серверов.html
5.  Вопрос Если~ нормальные напряжения по вертикальной оси через центр площади загрузки то увеличение пло
6. Антонов Юрий Михайлович
7. Ech mn shoots once t the trget
8. Лунаl запуск которого был осуществлен 2 января 1958 года
9. летию Москвы Мэр Москвы Столица нашей Родины Москва отмечает свое 850летие
10.  Дата и время несчастного случая число месяц год и время происшествия несчастного случая ко
11. Багратион, Петр Иванович
12. Поверь в себя Общие положения 1
13. За територіальним поширенням надзвичайні ситуації поділяють на рівні- а загальнодержавний; б регіон
14. тематическое смешение ведущее к появлению ненадежных данных фактор времени фактор задачи индивидуальные
15. Болезнь и смерть князя Андрея Болконского (Толстой, «Война и мир»)
16. і Для них характерні органи повітряного дихання
17. тематическое задание- Тогда простейший алгоритм будет выглядеть следующим образом- void DrawLineint x1 int y1 int x2
18. по теме Рок Тем более что рок считается молодежной культурой потому что
19. БИОГЕОГРАФИЯ С ОСНОВАМИ ЭКОЛОГИИ
20. Петербурге в 1714 Память о русском императоререформаторе и коллекционере запечатлена и в самом здании