Альфа-смешение: алгоритм выполнения

 

Оглавление


Введение

1. Постановка задачи

2. Описание используемых алгоритмов

2.1 Преобразование координат

2.2 Алгоритм удаления невидимых граней

2.3 Определение лицевых и не лицевых граней с помощью вектора нормали

2.4 Закраска трехмерного объекта с использованием простой модели освещения

3. Описание программы

3.1 Введенные типы данных и их предназначение

3.2 Основные переменные и их предназначение

3.3 Описание основных процедур и функций

3.4 Алгоритм взаимодействия процедур и функций

4. Тестирование программы

4.1 Описание интерфейса

4.2 Руководство по использованию программы

4.3 Результат

Заключение

Список использованных источников

Приложения

Введение


Компьютерная графика - это область деятельности, в которой компьютеры <#"justify">альфа смешение алгоритм графика

1. Постановка задачи


В данной работе требуется реализовать альфа-смешение, то есть создать трехмерные модели двух предметов: один прозрачный, другой нет. Цель работы заключается в том, чтобы наглядно показать свойства прозрачных тел, а именно отображение непрозрачного предмета сквозь прозрачный и сокрытие прозрачного предмета (или его части) за непрозрачным.

Создаваемая сцена будет состоять из двух предметов: трехмерной модели граненого стакана и модель куба. Стакан будет исполнять роль прозрачного предмета, а куб - непрозрачного. Стакан состоит из 20 боковых граней и грани основания стакана, все грани должны быть прозрачными. Куб - стандартная геометрическая модель, имеющая 6 граней, выполненных в форме правильных прямоугольников, квадратов. Данная сцена должна отражать эффект прозрачности и эффект освещения.

Рассмотрим координаты вершин модели стакана (таблица 1).


Таблица 1 - Координаты вершин модели стакана

Номер вершиныКоордината ХКоордината YКоордината Z0-50-5001-48-50-152-40-50-303-28-50-424-15-50-4850-50-50615-50-48728-50-42840-50-30948-50-151050-5001148-50151240-50301328-50421415-5048150-505016-15-504817-28-504218-40-503019-48-501520-60100021-58100-1922-48100-3623-35100-5024-18100-58250100-602618100-582735100-502848100-362958100-19306010003158100193248100363335100503418100583501006036-181005837-351005038-481003639-5810019

В данном случае стакан представлен в цилиндра, с более широким верхом и менее широким основанием. Вершины от 0 по 19 составляют основание стакана, с помощью этого диапазона вершин строится грань основания стакана. Вершины от 20 до 39 составляют верхнюю грань стакана, но учитываю специфичную форму сосуда, грань из этих вершин строить не будем. В данном стакане предусмотрено 20 боковых граней, каждая грань строится по принципу соединения вершин в один полигон, например: одна из боковых граней имеет вершины 0, 20, 21, 1 (цикл: i, i + 20, i + 21, i + 1).

Рассмотрим координаты вершин куба с ребром 50 (таблица 2).

Таблица 2 - Координаты вершин куба

Номер вершиныКоордината ХКоордината YКоордината ZОснование куба40-60-50-6541-60-50-11542-10-50-11543-10-50-65Верхняя грань44-600-6545-600-11546-100-11547-100-65

Модель куба собирается по аналогичному принципу моделирования стакана, сначала формируем грань основания, потом верхнюю грань, а потом создаем боковые грани. Каждая грань куба задается 4 вершинами. Так как эти две модели образуют единую сцену, то координаты отсчитываются по единой системе, а также номера вершин задаются по порядку. В дальнейшем к разрабатываемым объектам сцены будет применено закрашивание граней, введение прозрачности и создание освещения всей сцены.

2. Описание используемых алгоритмов


.1 Преобразование координат


В предыдущем разделе для построения трехмерных объектов были заданы координаты вершин объектов в мировой системе координат. Необходимо получить из заданных координат видовые (и экранные для ортогональной проекции) координаты. Для видовых координат следует применить перспективные преобразования для придачи разрабатываемым объектам реалистичности. Конечно, можно собрать трехмерную модель без использования перспективного преобразования, но тогда возможен так называемый обман зрения, возникающий из-за ракурса модели, но применив перспективные преобразования, данный эффект исчезнет. Экранные координаты вершин получим после того, как к видовым координатам применим перспективные преобразования, в данном случае и будем собирать наши модели.


// Видовые координаты:[i]. x = 20 * (int) Math. Round (Vertex [i]. x * (-Math. Sin (teta)) + Vertex [i]. y * Math. Cos (teta));[i]. y = 20 * (int) Math. Round (Vertex [i]. x * (-Math. Cos (phi) * Math. Cos (teta)) - Vertex [i]. y * (Math. Cos (phi) * Math. Sin (teta)) + Vertex [i]. z * Math. Sin (phi));[i]. z = - 20 * (int) Math. Round (Vertex [i]. x * (-Math. Sin (phi) * Math. Cos (teta)) - Vertex [i]. y * (Math. Sin (phi) * Math. Sin (teta)) - Vertex [i]. z * (Math. Cos (phi)) + R0);

// Перспективное преобразование

Perspective [i]. X = pictureBox1. Width / 2 + (int) Math. Round (D0 * (View [i]. x / View [i]. z));[i]. Y = pictureBox1. Height / 2 + (int) Math. Round (D0 * (View [i]. y / View [i]. z));

// Получение экранных координат

Scrn [i]. X = (int) Perspective [i]. X + pictureBox1. Width / 2;[i]. Y = (int) Perspective [i]. Y + pictureBox1. Height / 2;

Рисунок 1 - Получение экранных координат


Более подробный алгоритм можно показан в приложении А, где указан листинг программы.

2.2 Алгоритм удаления невидимых граней


Так как в двумерном пространстве строится трехмерная модель, то из-за этого возникает эффект перекрытия граней, то есть грани отрисовываются в одном и том же месте. Чтобы этого избежать, следует показывать только лицевые грани, а невидимые грани удалять. Для этого воспользуемся алгоритмом Ньюла-Ньюэла-Санча, иначе называющимся алгоритм художника. Идея алгоритма художника, состоит в том, что, используя упорядоченность граней по глубине, выводится с закраской грани, начиная с дальних граней. При этом грани, которые выводятся позже, закрывают собою невидимые части более дальних граней. Часть этого метода работает в пространстве объекта, а часть в пространстве изображения. Он также работает для параллельной проекции, то есть с учетом того, что произведено перспективное преобразование.

Метод состоит из трех основных шагов:

. упорядочение всех полигонов в соответствии с их наибольшими z-координатами;

. разрешение всех неопределенностей, которые возникают при перекрытии z-оболочек многоугольников;

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

Для нахождения среднего значения по координате Z, необходимо сложить значения координаты Z каждой из вершин полигона и поделить эту сумму на количество вершин. Это и будет среднее значение координаты Z полигона. Далее создадим массив, содержащий все средние значения, и попарно будем сравнивать их. Если данное значение будет меньше предыдущего, то значит, что полигон находится ближе к наблюдателю, а значит, будет рисоваться в последнюю очередь. Таким образом, грани будут появляться в порядке уменьшения значения Z.

Данный алгоритм отличается чрезмерной простотой реализации, и, как следствие, недостаточно эффективен. В самом деле, если трехмерная сцена состоит из большого количества объектов, в среднем половина полигонов будет не видна в текущем кадре. А значит, их отображение на экране и не требуется. Недостаток "алгоритма художника" состоит в том, что отображаются все полигоны.


.3 Определение лицевых и не лицевых граней с помощью вектора нормали


Для сокращения числа полигонов можно вычислить для каждой грани вектор нормали, и по его значению определить грани, которые будут видны. Сразу стоит отметить то, что наша сцена состоит из прозрачного объекта и непрозрачного, поэтому немного модернизируем данный алгоритм.

Идея алгоритма состоит в том, что по углу между направлением взгляда и нормалью к поверхности можно определить расположение граней, лицевая она или же нет. Нормаль к поверхности находится с помощью трех точек, так как через любые три точки можно провести плоскость. Координаты вектора нормали следующие: N (Nx, Ny, Nz). Три точки поверхности имеют следующие координаты: A (Ax, Ay, Az), B (Bx, By, Bz), C (Cx, Cy, Cz). Уравнение плоскости задается в виде:


Nx * X + Ny * Y + Nz * Z + d = 0.


В результате получим следующую систему уравнений:



Преобразуем данную систему в матрицу размером 4Х4.



Найдем определитель данной матрицы по первой строке. Так как данная система уравнений имеет нетривиальное решение, то определитель данной матрицы равен 0. В результате получаем:


Nx = , Ny = , Nz = .


Значение d для определения координат вектора не нужно. Итак, координаты вектора нормали имеют вид:


Nx = Ay (Bz - Cz) + By (Cz - Az) + Cy (Az - Bz);

Ny = Az (Bx - Cx) + Bz (Cx - Ax) + Cz (Ax - Bx);

Nz = Ax (By - Cy) + Bx (Cy - Ay) + Cx (Ay - By).


Осталось привести вектор нормали к единичной длине, так как для определения косинуса угла между векторами проще использовать единичные векторы. Для этого нужно определить длину вектора и разделить на нее каждую координату. Для каждой грани при инициализации объекта нужно посчитать вектор нормали, привести к единичной длине и сохранить его координаты в структуре соответствующей грани. Кроме того, при каждом повороте сцены векторы нормали нужно тоже пересчитывать (но перспективную проекцию находить не следует).

Для реализации данного алгоритма нам потребуется только координата Nz. Значение получим по формуле: Nz = Nz/ (Корень (Nx*Nx + Ny*Ny + Nz*Nz)).

Если Nz > 0, то грань не видна, если Nz < 0, то грань видна. Так как у нас на сцене имеется прозрачный объект, у которого должны прорисовываться все грани, то выполним оба условия на проверку видимости граней.


2.4 Закраска трехмерного объекта с использованием простой модели освещения


Так как расчет нормалей в нашей сцене мы уже реализовали, то добавить освещение к нашим объектам уже не составит больших проблем. Помимо освещенности будем одновременно закрашивать получившиеся поверхности объектов. Идея алгоритма состоит в следующем: будем закрашивать каждую грань объекта, умножив значение заданного цветового канала (A, R, G, B) на значение координаты Z вектора нормали. Цвет и настройки прозрачности у объектов разные, но система цветов одна, поэтому зададим предварительно значения альфа-канала для граней куба полностью непрозрачными - 255, а для граней стакана значения определим следующие: 80 для боковых граней, и 100 для основания стакана. Чем больше значение Nz будет приближаться к единице, тем меньше будет угол между нормалью и лучом света и тем соответственно больше будет интенсивность цвета.

Для закраски полигонов воспользуемся стандартной функцией закраски - FillPolygon. Данная функция заполняет внутреннюю часть полигона, определяемого массивом точек, один из двух параметров данной функции отвечает за цвет закраски. В итоге получаем простейшую, но эффектную систему освещения.


3. Описание программы


3.1 Введенные типы данных и их предназначение


В таблице 3 указаны все типы данных, используемые в программе.


Таблица 3 - Типы данных, используемые в программе

Тип данныхПредназначениеintИспользуются для целочисленных вычисленийdoubleИспользуются для точных вычисленийboolИспользуется для логических преобразований и операцийint [] Используется в качестве массивов, хранящих целые значения (номера полигонов, вершин) double [] Используется в качестве массивов, хранящих вещественные числа, например массив, хранящий средние значения координаты ZСтруктурыИспользуются для описания координат вершинКлассыИспользуются для возможности реализации методов и функций программы

3.2 Основные переменные и их предназначение


Основные переменные и их предназначение рассмотрены в таблице 4.


Таблица 4 - Основные переменные и их функции

ПеременнаяТип данныхФункцияbКласс BitmapИспользуется для работы с изображениями, определяемыми данными пикселейgКласс GraphicsИнкапсулирует поверхность рисованияimageКласс ImageПозволяет загрузить фоновое изображение для компонентов программыVertexPoint3D [] Определяет структуру координат вершинViewPoint3D [] Видовые координаты вершинScrnPoint [] Массив экранных координатPerspectivePoint [] Массив перспективных координатNZdouble [] Массив, содержащий все значения координаты Z вектора нормалиOrderint [] Массив, задающий порядок отображения граней, порядковые номера полигоновDdouble [] Массив, хранящий среднее значение по координате Z плоскостиTeta, PhidoubleПеременные, хранящие значения угловnx, ny, nzdoubleКоординаты вектора нормалиR0intКоэффициент масштабирования сценыD0intКоэффициент перспективы сценыmousePressboolЛогическая переменная, отслеживающая нажатие на кнопку мыши

3.3 Описание основных процедур и функций


Рассмотрим основные функции и процедуры.

.Процедура "ПостроитьСцену". Главная процедура, в которой происходит преобразование координат, создание полигонов, вычисление средних значений координаты Z, закрашивание поверхностей и создание модели освещения.

2.Функция "СортировкаГраней". Сортирует грани по глубине и заполняет массив упорядоченных граней для отображения.

.Процедура "ВычислениеНормали". Вычисляет нормаль к поверхности и заполняет массив с координатой Z этой нормали.

.Процедура "ПоказатьСцену". Данная процедура используется для перерисовки сцены.

.Функция "Flag". Вспомогательный метод для реализации функции "СортировкаГраней". Определяет грани для сравнения.


.4 Алгоритм взаимодействия процедур и функций


Рассмотрим алгоритм взаимодействия вышеописанных процедур и функций. Процедура "ПоказатьСцену" вызывается каждый раз при изменении изображения сцены, данная процедура содержит в своем теле основную процедуру программы "ПостроениеСцены". Процедура "ПостроениеСцены" помимо своих наборов действий состоит из функции: "СортировкаГраней" и функции "ВычислениеНормали". Функция "СортировкаГраней" включает в себе метод "Flag". Условная схема взаимодействия процедур и функций представлена на рисунке 2.


Рисунок 2 - Условная схема взаимодействия процедур и функций

4. Тестирование программы


4.1 Описание интерфейса


При запуске программы пользователь сразу видит сцену: стакан и куб перед ним (рисунок 3).


Рисунок 3 - Интерфейс программы


Программа имеет интуитивно понятный интерфейс, то, что было заявлено, то и получилось - два объекта: прозрачный объект (стакан) и непрозрачный (куб). А также надпись на самой форме "С# Alpha Blending" говорит о теме работы, альфа смешении. Окно приложения нельзя масштабировать, можно только закрывать и сворачивать. Заголовок окна приложения также дает понять о тематике приложения.


4.2 Руководство по использованию программы


Данное приложение предназначено для подтверждения свойств тел, таких как прозрачность и непрозрачность, а также для наблюдения того, как ведут себя предметы, обладающие данными свойствами в пределах одной сцены. То есть прозрачное тело, перекрывая непрозрачное, должно полностью его отображать, а непрозрачное тело в свою очередь должно скрывать часть прозрачного тела или любого другого, находящегося с ним на одной сцене.

Пользователь может изучать данные предметы путем их вращения или масштабирования. Обзор сцены выполняется либо с помощью мыши, либо с помощью стрелок клавиатуры. Система управления представлена в таблице 5.


Таблица 5 - Управления сценой

Элемент управленияДействиеМышьЗажатая ЛКМ/ПКМОбзор сцены со всех ракурсовВращение колесикаМасштабирование +/-Нажатие ПКМПривидение к сходному размеруКлавиатураВверхВращение сцены вертикально вверхВнизВращение сцены вертикально внизВлевоВращение сцены в левую сторонуВправоВращение сцены в правую сторону

Данное приложение работает без аварийных завершений, не вызывает исключений, не перегружает систему, не помечается антивирусными системами как потенциально опасное программное обеспечение.

Минимальные системные требования:

-операционная система Windows XP, Vista, 7 (совместимость сWindows 8 неизвестна);

-процессор с тактовой частотой 1 Ггц или выше;

ОЗУ 512 Мб или выше;

-Видеопамять 128 Мб или выше;

-Клавиатура, мышь.

4.3 Результат


В результате выполнения программы, получаем следующие результаты, показанные на рисунках 4-8.


Рисунок 4 - Часть стакана скрыта непрозрачным кубом


Рисунок 5 - Видимость куба сквозь прозрачный стакан


Рисунок 6 - Куб находится позади стакана


Рисунок 7 - Пример масштабирования на уменьшение сцены


Рисунок 8 - Пример масштабирования на увеличение сцены


Заключение


В результате выполнения поставленной задачи, получили сцену, состоящую из двух предметов (прозрачный стакан и непрозрачный куб) на статичном фоне, замощенным загруженным изображением. По заданию необходимо было доказать свойства прозрачных тел и свойства непрозрачных тел, а также проверить это опытным путем в результате их взаимодействия. В итоге получили необходимые результаты: непрозрачный предмет скрывает часть прозрачного предмета, а сквозь прозрачный предмет при любом ракурсе виден непрозрачный предмет.

Для получения данных результатов был применен ряд алгоритмов: алгоритм преобразования координат, алгоритм удаления невидимых граней, алгоритм, определяющий лицевые и не лицевые грани с помощью вектора нормали, проведенного к поверхности, а также алгоритм закраски трехмерного объекта с использованием простой модели освещения, основанной на ранее вычисленных значениях вектора нормали.

Итогом работы стало приложение "C# Alpha Blending", наглядно показывающий принцип работы альфа-смешения, а также доказывающий возможность создания трехмерной сцены посредством программирования на языке высокого уровня C#.

Список использованных источников


1 Кузнецова Е.А., Лукошков М.М., Майоров И.С. Методические указания к выполнению лабораторных работ по дисциплине "Компьютерная геометрия и графика". [Текст] - Издательство: " Архангельский Государственный Технический Университет", г. Архангельск, 2006 г. - стр.36;

2 Википедия - Свободная Энциклопедия. [Электронный Ресурс] - Режим доступа: #"center">Приложения


Приложение А


Листинг основных компонентов

Листинг модуля Form1. csSystem;System. Collections. Generic;System.componentModel;System. Data;System. Drawing;System. Linq;System. Text;System. Windows. Forms;WindowsFormsApplication1

{

// Структура координатstruct Point3D

{double x;double y;double z;Point3D (double x, double y, double z)

{. x = x;. y = y;. z = z;

}

}partial class Form1: Form

{b;g;image;D [] Vertex = new Point3D [48]; // Массив координат вершин (x, y, z)D [] View = new Point3D [48]; // Массив видовых координат[] Scrn = new Point [48]; // Массив экранных координат[] Perspective = new Point [48]; // Массив перспективных координат[] NZ = new double [27]; // Массив нормалей для освещения

int [] Order = new int [27]; // Массив порядка отображения видимых граней[] D = new double [27]; // Массив, содержащий средние значения Z-гранейTeta = Math. PI / 180; // Угол тета = 45 градусов

double Phi = Math. PI / 180; // Угол фи = 45 градусовmousePress = false;sX = 0;sY = 0;nx, ny, nz;D0 = 500;R0 = 300;Form1 ()

{();. MouseWheel += new MouseEventHandler (Form1_MouseWheel);= new Bitmap ("Background. jpg"); // Экземпляр класса Bitmap= Image. FromFile ("Background. jpg"); // Загружаем фоновое изображение

g = Graphics. FromImage (b); // Задаем поверхность для рисования

}

// Построение объектов сценыПостроитьСцену ()

{. DrawImage (image, 0, 0);(int i = 0; i < 48; i++)

{

// Преобразование из мировых в видовые координаты

View [i]. x = 20 * (int) Math. Round (Vertex [i]. x * (-Math. Sin (Teta)) + Vertex [i]. y * Math. Cos (Teta));[i]. y = 20 * (int) Math. Round (Vertex [i]. x * (-Math. Cos (Phi) * Math. Cos (Teta)) - Vertex [i]. y * (Math. Cos (Phi) * Math. Sin (Teta)) + Vertex [i]. z * Math. Sin (Phi));[i]. z = - 20 * (int) Math. Round (Vertex [i]. x * (-Math. Sin (Phi) * Math. Cos (Teta)) - Vertex [i]. y * (Math. Sin (Phi) * Math. Sin (Teta)) - Vertex [i]. z * (Math. Cos (Phi)) + R0);

// Перспективное преобразование видовых координат

Perspective [i]. X = pictureBox1. Width / 2 + (int) Math. Round (D0 * (View [i]. x / View [i]. z));[i]. Y = pictureBox1. Height / 2 + (int) Math. Round (D0 * (View [i]. y / View [i]. z));(View [i]. z == 0)

{[i]. X = 0;[i]. Y = 0;

}

{[i]. X = (int) (Math. Round (D0 * (View [i]. x / View [i]. z)));[i]. Y = (int) (Math. Round (D0 * (View [i]. y / View [i]. z)));

}

// Получение экранных координат

Scrn [i]. X = (int) Perspective [i]. X + pictureBox1. Width / 2;[i]. Y = (int) Perspective [i]. Y + pictureBox1. Height / 2;

}

// Находим среднее значение по координате Z каждой грани

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

{[i] = (View [i]. z + View [i + 20]. z + View [i + 21]. z + View [i + 1]. z) / 4;

}

// Конечная грань стакана[19] = (View [19]. z + View [39]. z + View [20]. z + View [0]. z) / 4;

// Грань - основание стакана

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

{

D [20] += View [i]. z / 20;

}

// Грани ядовито-желтого куба

D [21] = (View [40]. z + View [41]. z + View [42]. z + View [43]. z) / 4;[22] = (View [40]. z + View [44]. z + View [47]. z + View [43]. z) / 4;[23] = (View [43]. z + View [47]. z + View [46]. z + View [42]. z) / 4;[24] = (View [42]. z + View [46]. z + View [45]. z + View [41]. z) / 4;[25] = (View [41]. z + View [45]. z + View [44]. z + View [40]. z) / 4;[26] = (View [44]. z + View [45]. z + View [46]. z + View [47]. z) / 4;

// Заполняем список граней<Point [] > Plane = new List<Point [] > ();(int i = 0; i < 19; i++)

{. Add (new Point [] { Scrn [i], Scrn [20 + i], Scrn [21 + i], Scrn [1 + i] });

}. Add (new Point [] { Scrn [19], Scrn [39], Scrn [20], Scrn [0] });. Add (new Point [] {Scrn [0], Scrn [1], Scrn [2], Scrn [3], Scrn [4], Scrn [5], Scrn [6], Scrn [7], Scrn [8], Scrn [9], Scrn [10], Scrn [11], Scrn [12], Scrn [13], Scrn [14], Scrn [15], Scrn [16], Scrn [17], Scrn [18], Scrn [19] });

// Куб ядовито-желтого цвета

Plane. Add (new Point [] { Scrn [40], Scrn [41], Scrn [42], Scrn [43] });. Add (new Point [] { Scrn [40], Scrn [44], Scrn [47], Scrn [43] });. Add (new Point [] { Scrn [43], Scrn [47], Scrn [46], Scrn [42] });. Add (new Point [] { Scrn [42], Scrn [46], Scrn [45], Scrn [41] });. Add (new Point [] { Scrn [41], Scrn [45], Scrn [44], Scrn [40] });. Add (new Point [] { Scrn [44], Scrn [45], Scrn [46], Scrn [47] });

// Список цветов для граней сцены<Color> PlaneColor = new List<Color> ()

{. FromArgb (80, 208, 208, 208), // 1 Грань стакана. FromArgb (80, 208, 208, 208), // 2 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 3 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 4 Грань стакана. FromArgb (80, 208, 208, 208), // 5 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 6 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 7 Грань стакана. FromArgb (80, 208, 208, 208), // 8 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 9 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 10 Грань стакана. FromArgb (80, 208, 208, 208), // 11 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 12 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 13 Грань стакана. FromArgb (80, 208, 208, 208), // 14 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 15 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 16 Грань стакана. FromArgb (80, 208, 208, 208), // 17 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 18 Грань стакана

Color. FromArgb (80, 208, 208, 208), // 19 Грань стакана. FromArgb (80, 208, 208, 208), // 20 Грань стакана

Color. FromArgb (100, 102, 102, 102), // 21 - основание стакана

Color. FromArgb (255, 204, 255, 0), // Грань куба

Color. FromArgb (255, 204, 255, 0), // Грань куба

Color. FromArgb (255, 204, 255, 0), // Грань куба

Color. FromArgb (255, 204, 255, 0), // Грань куба

Color. FromArgb (255, 204, 255, 0), // Грань куба. FromArgb (255, 204, 255, 0), // Грань куба

};

СортировкаГраней (27, 0); // Сортировка 27 граней по глубине, начиная с 0-ой грани

ВычислениеНормали (); // Вычисление нормали к плоскости по трем точкам

for (int i = 0; i < 27; i++) // Перебираем все грани

{(NZ [Order [i]] >= 0) // Если грань не видна

{A = (int) ( (double) PlaneColor [Order [i]]. A); // ПрозрачностьR = (int) ( (double) PlaneColor [Order [i]]. R * NZ [Order [i]]); // Красный цвет * интенсивность

int G = (int) ( (double) PlaneColor [Order [i]]. G * NZ [Order [i]]); // Зеленый цвет * интенсивность

int B = (int) ( (double) PlaneColor [Order [i]]. B * NZ [Order [i]]); // Синий цвет * интенсивность

Color Glass = Color. FromArgb (A, R, G, B); // Задаем цвет. FillPolygon (new SolidBrush (Glass), Plane [Order [i]]); // Закраска

}

if (NZ [Order [i]] <= 0) // Если грань видна

{A = (int) Math. Abs ( ( (double) PlaneColor [Order [i]]. A));R = (int) Math. Abs ( ( (double) PlaneColor [Order [i]]. R * NZ [Order [i]]));G = (int) Math. Abs ( ( (double) PlaneColor [Order [i]]. G * NZ [Order [i]]));B = (int) Math. Abs ( ( (double) PlaneColor [Order [i]]. B * NZ [Order [i]]));Glass = Color. FromArgb (A, R, G, B);

g. FillPolygon (new SolidBrush (Glass), Plane [Order [i]]);

}

}

}

// Процедура нахождения нормалей к поверхностямВычислениеНормали ()

{

// Получение нормалей к первым 19 граням стакана

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

{= View [i]. y * (View [i + 20]. z - View [i + 21]. z) + View [i + 20]. y * (View [i + 21]. z - View [i]. z) + View [i + 21]. y * (View [i]. z - View [i + 20]. z);= View [i]. z * (View [i + 20]. x - View [i + 21]. x) + View [i + 20]. z * (View [i + 21]. x - View [i]. x) + View [i + 21]. z * (View [i]. x - View [i + 20]. x);= View [i]. x * (View [i + 20]. y - View [i + 21]. y) + View [i + 20]. x * (View [i + 21]. y - View [i]. y) + View [i + 21]. x * (View [i]. y - View [i + 20]. y);[i] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

}

// Нормаль к 19-ой грани (не поддается циклу)

nx = View [19]. y * (View [39]. z - View [20]. z) + View [39]. y * (View [20]. z - View [19]. z) + View [20]. y * (View [19]. z - View [39]. z);= View [19]. z * (View [39]. x - View [20]. x) + View [39]. z * (View [20]. x - View [19]. x) + View [20]. z * (View [19]. x - View [39]. x);= View [19]. x * (View [39]. y - View [20]. y) + View [39]. x * (View [20]. y - View [19]. y) + View [20]. x * (View [19]. y - View [39]. y);[19] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

// Нормаль к грани (основание стакана), грань имеет 10 вершин, взято 3 (0, 10, 19)

nx = View [0]. y * (View [10]. z - View [19]. z) + View [10]. y * (View [19]. z - View [0]. z) + View [19]. y * (View [0]. z - View [10]. z);= View [0]. z * (View [10]. x - View [19]. x) + View [10]. z * (View [19]. x - View [0]. x) + View [19]. z * (View [0]. x - View [10]. x);= View [0]. x * (View [10]. y - View [19]. y) + View [10]. x * (View [19]. y - View [0]. y) + View [19]. x * (View [0]. y - View [10]. y);[20] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

// 40, 41, 42= View [40]. y * (View [41]. z - View [42]. z) + View [41]. y * (View [42]. z - View [40]. z) + View [42]. y * (View [40]. z - View [41]. z);= View [40]. z * (View [41]. x - View [42]. x) + View [41]. z * (View [42]. x - View [40]. x) + View [42]. z * (View [40]. x - View [41]. x);= View [40]. x * (View [41]. y - View [42]. y) + View [41]. x * (View [42]. y - View [40]. y) + View [42]. x * (View [40]. y - View [41]. y);[21] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

// 40, 44, 47= View [40]. y * (View [44]. z - View [47]. z) + View [44]. y * (View [47]. z - View [40]. z) + View [47]. y * (View [40]. z - View [44]. z);= View [40]. z * (View [44]. x - View [47]. x) + View [44]. z * (View [47]. x - View [40]. x) + View [47]. z * (View [40]. x - View [44]. x);= View [40]. x * (View [44]. y - View [47]. y) + View [44]. x * (View [47]. y - View [40]. y) + View [47]. x * (View [40]. y - View [44]. y);[22] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

// 43, 47, 46= View [43]. y * (View [47]. z - View [46]. z) + View [47]. y * (View [46]. z - View [43]. z) + View [46]. y * (View [43]. z - View [47]. z);= View [43]. z * (View [47]. x - View [46]. x) + View [47]. z * (View [46]. x - View [43]. x) + View [46]. z * (View [43]. x - View [47]. x);= View [43]. x * (View [47]. y - View [46]. y) + View [47]. x * (View [46]. y - View [43]. y) + View [46]. x * (View [43]. y - View [47]. y);[23] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

// 42, 46, 45= View [42]. y * (View [46]. z - View [45]. z) + View [46]. y * (View [45]. z - View [42]. z) + View [45]. y * (View [42]. z - View [46]. z);= View [42]. z * (View [46]. x - View [45]. x) + View [46]. z * (View [45]. x - View [42]. x) + View [45]. z * (View [42]. x - View [46]. x);= View [42]. x * (View [46]. y - View [45]. y) + View [46]. x * (View [45]. y - View [42]. y) + View [45]. x * (View [42]. y - View [46]. y);[24] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

// 41, 45, 44= View [41]. y * (View [45]. z - View [44]. z) + View [45]. y * (View [44]. z - View [41]. z) + View [44]. y * (View [41]. z - View [45]. z);= View [41]. z * (View [45]. x - View [44]. x) + View [45]. z * (View [44]. x - View [41]. x) + View [44]. z * (View [41]. x - View [45]. x);= View [41]. x * (View [45]. y - View [44]. y) + View [45]. x * (View [44]. y - View [41]. y) + View [44]. x * (View [41]. y - View [45]. y);[25] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

// 44, 45, 46= View [44]. y * (View [45]. z - View [46]. z) + View [45]. y * (View [46]. z - View [44]. z) + View [46]. y * (View [44]. z - View [45]. z);= View [44]. z * (View [45]. x - View [46]. x) + View [45]. z * (View [46]. x - View [44]. x) + View [46]. z * (View [44]. x - View [45]. x);= View [44]. x * (View [45]. y - View [46]. y) + View [45]. x * (View [46]. y - View [44]. y) + View [46]. x * (View [44]. y - View [45]. y);[26] = nz / Math. Sqrt (nz * nz + ny * ny + nx * nx);

}

// Получить изображение кубаПоказатьСцену ()

{

ПостроитьСцену ();. Image = b;

}

// Метод-флаг

bool Flag (int i, int PlaneNumber, int [] Order)

{flag = true; // Флаг поднят(int j = 0; j < PlaneNumber; j++) // Перебираем грани по их номерам

if (Order [j] == i) flag = false; // Сравниваем номер грани в массиве порядка с номером данной граниflag; // Возвращаем значение флага

}

// Метод сортировки гранейСортировкаГраней (int PlanesCount, int PlaneNumber)

{k = 1000; // Показатель глубины

for (int i = 0; i < 27; i++) // Перебираем все грани

{(Flag (i, PlaneNumber, Order)) //

if (D [i] < k) // Если ср. знач. по Z < показателя глубины

{ // то.= D [i]; // Показатель глубины равняется конкретному значению[PlaneNumber] = i; // Заполнения массива по порядку расположения граней

}

}- -; // Уменьшаем количество граней на 1++; // Увеличиваем номер грани на 1(PlanesCount > 0) // Если количество граней > 0, вызываем рекурсию

СортировкаГраней (PlanesCount, PlaneNumber);

}

// События, обрабатываемые при загрузке формы приложения

private void Form1_Load (object sender, EventArgs e)

{= 89.549087;= 134.99817;[0] = new Point3D (-50, - 50, 0); // A[1] = new Point3D (-48, - 50, - 15); // B[2] = new Point3D (-40, - 50, - 30); // C[3] = new Point3D (-28, - 50, - 42); // D[4] = new Point3D (-15, - 50, - 48); // E[5] = new Point3D (0, - 50, - 50); // F[6] = new Point3D (15, - 50, - 48); // G[7] = new Point3D (28, - 50, - 42); // H[8] = new Point3D (40, - 50, - 30); // I[9] = new Point3D (48, - 50, - 15); // J[10] = new Point3D (50, - 50, 0); // K[11] = new Point3D (48, - 50, 15); // L[12] = new Point3D (40, - 50, 30); // M[13] = new Point3D (28, - 50, 42); // N[14] = new Point3D (15, - 50, 48); // O[15] = new Point3D (0, - 50, 50); // P[16] = new Point3D (-15, - 50, 48); // R[17] = new Point3D (-28, - 50, 42); // S[18] = new Point3D (-40, - 50, 30); // T [19] = new Point3D (-48, - 50, 15); // U

// Верхняя плоскость стакана

Vertex [20] = new Point3D (-60, 100, 0); // A-1[21] = new Point3D (-58, 100, - 19); // B-1[22] = new Point3D (-48, 100, - 36); // C-1[23] = new Point3D (-35, 100, - 50); // D-1[24] = new Point3D (-18, 100, - 58); // E-1[25] = new Point3D (0, 100, - 60); // F-1[26] = new Point3D (18, 100, - 58); // G-1[27] = new Point3D (35, 100, - 50); // H-1[28] = new Point3D (48, 100, - 36); // I-1[29] = new Point3D (58, 100, - 19); // J-1[30] = new Point3D (60, 100, 0); // K-11[31] = new Point3D (58, 100, 19); // L-12[32] = new Point3D (48, 100, 36); // M-13[33] = new Point3D (35, 100, 50); // N-14[34] = new Point3D (18, 100, 58); // O-15[35] = new Point3D (0, 100, 60); // P-16[36] = new Point3D (-18, 100, 58); // R-17[37] = new Point3D (-35, 100, 50); // S-18[38] = new Point3D (-48, 100, 36); // T-19[39] = new Point3D (-58, 100, 19); // U-20

// Ядовито-желтый куб (а = 50)

// Нижняя грань

Vertex [40] = new Point3D (-60, - 50, - 65); // A[41] = new Point3D (-60, - 50, - 115); // B[42] = new Point3D (-10, - 50, - 115); // C[43] = new Point3D (-10, - 50, - 65); // D

// Верхняя грань[44] = new Point3D (-60, 0, - 65); // A-1[45] = new Point3D (-60, 0, - 115); // B-1[46] = new Point3D (-10, 0, - 115); // C-1[47] = new Point3D (-10, 0, - 65); // D-1

ПоказатьСцену ();

}

// Управление сценой с помощью клавиш-стрелок

private void Form1_KeyDown (object sender, KeyEventArgs e)

{(e. KeyCode == Keys. Up)

{= Phi + Math. PI / 128;

ПоказатьСцену ();

}(e. KeyCode == Keys. Down)

{= Phi - Math. PI / 128;

ПоказатьСцену ();

}(e. KeyCode == Keys. Right)

{= Teta + Math. PI / 128;

ПоказатьСцену ();

}(e. KeyCode == Keys. Left)

{= Teta - Math. PI / 128;

ПоказатьСцену ();

}

}

// Управление сценой с помощью мышиvoid pictureBox1_MouseMove (object sender, MouseEventArgs e)

{(mousePress)

{(e. X < sX)

{= Teta - Math. PI / 128;= e. X;

}(e. X > sX)

{= Teta + Math. PI / 128;= e. X;

}(e. Y > sY)

{= Phi - Math. PI / 128;= e. Y;

}(e. Y < sY)

{= Phi + Math. PI / 128;= e. Y;

}

ПоказатьСцену ();

}

}

// Событие, вохникающее при отпускании мыши

private void pictureBox1_MouseUp (object sender, MouseEventArgs e)

{= false;

}

// Событие, возникающее при нажатии мыши

private void pictureBox1_MouseDown (object sender, MouseEventArgs e)

{= true;(e. Button == MouseButtons. Right)

{= 300;

ПоказатьСцену ();

}

}

// Событие при прокрутке колеса мыши

void Form1_MouseWheel (object sender, MouseEventArgs e)

{( (e. Delta == 120) && (R0! = 150))

{- = 5;

ПоказатьСцену ();

}if ( (e. Delta == - 120) && (R0! = 800))

{+= 5;

ПоказатьСцену ();

}

}

}

}


Оглавление Введение 1. Постановка задачи 2. Описание используемых алгоритмов 2.1 Преобразование координат 2.2 Алгоритм удаления невидимых гра

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2018 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ