,(4.4)
|
|
где -
позиция два шага назад.
Не зависит от значения скорости частицы.
Время шага должно быть константой.
Явное манипулирование скоростью (например для
расчета столкновений) невозможно.[4]
Рисунок 4.3- Интегрирование Верле
На чем моделировать?
Выбор устройства, на котором будут производиться
основные вычисления, прямым образом влияет на производительность.- центральный
процессор
Основное ядро
Другое ядро- графический процессор
Вершинный шейдер
Пиксельный шейдер
Геометрический шейдер
Моделирование на CPU
Достоинства:
Просто, прямолинейно
Все возможно
Недостатки:
Процессор общего назначения не оптимизирован для
этого.
Использование тактов, которые могли бы быть
использованы для более сложных алгоритмов, например геймплея или искусственного
интеллекта.
Требуется загружать результирующие данные
моделирования для отрисовки каждого кадра[4].
Моделирование на вершинном шейдере
Может моделировать только по вышеописанному
методу “функции в замкнутой форме”
Принцип работы:
При «рождении» частиц в динамический вершинный
буфер загружаются время рождения и начальные значения. В крайних случаях нужно
загрузить только «случайное начальное заполнение» (random seed) в качестве
начального значения.
При отрисовке установить глобальные параметры
функции как константы вершинного шейдера.
Отрисовать точечные спрайты/ треугольники/
квадраты с вершинным шейдером системы частиц[4].
Моделирование на пиксельном шейдере
Данные позиции и скорости записываются в
текстуры.
На каждом шаге моделирования из этих текстур
отрисовывются в другие одинаковые по размеру текстуры.
Пиксельный шейдер выполняет итерационное интегрирование
(Эйлера или Верле)
Позиция текстуры представляется как данные
вершины.
Отрисовываются точечные спрайты/ треугольники/
квадраты.
Для конечной отрисовки необходимо использовать
текстуру позиций для генерирования вершин. Существует два концептуальных
варианта:
Отрисовка в вершинный буфер (R2VB)
Доступна на консолях и на DX10
Доступна на DX9 в неофициальном расширении ATI.
Не общедоступно на DX9!
Доступно на OpenGL через расширения.
Вершинные текстуры
Обращение к текстурам из вершинного шейдера
Вершинный шейдер считывает позиции из статичного
вершинного буфера и по этим позициям считывает данные из текстур.
Доступно на DX9 (VS3.0, кроме ATI X1xxx)
Доступно на OpenGL (VS3.0)
Высокое время ожидания на ранних аппаратных
средствах c VS3.0.VB обычно имеет более высокую производительность[4].
Моделирование на геометрическом шейдере
Геометрический шейдер может создавать новые или
уничтожать старые данные. Что можно использовать для рождения/уничтожения
частиц.
Доступно на DX10 и OpenGL на аппаратных
средствах с SM4.0[4].
Обоснование выбора.
В качестве средств разработки были выбраны язык
программирования C#, набор библиотек XNA 4.0 и среда разработки Visual Studio
2010.- новая, быстро развивающаяся библиотека для разработки игр и графических
приложений. XNA позволяет создавать приложения для Windows, Xbox 360, Zune и
Windows Phone.
Так как XNA базируется на DirectX9, то
моделирование на геометрическом шейдере не представляется доступным, а
пиксельный и вершинный шейдер не достаточно гибки для разработки библиотеки.
Для того чтобы обеспечить гибкость библиотеки было решено производить все
вычисления на центральном процессоре.
В качестве алгоритма моделирования было выбрано
интегрирование Эйлера, из-за простоты вычислений, а так же потому что другие
методы не позволяют манипулировать текущим значением скорости частицы (например
расчета столкновений).
Частицы будут отображаться при помощи
биллбордов. Это объясняется следующими факторами:
В XNA 4.0 прекращена поддержка точечных
примитивов.
На биллборд можно наложить текстуру.
При маленьких размерах биллборд не отличить от
точечного примитива.
Описание разработки
Библиотека состоит из следующего набора классов:
Класс Particle;
Класс
ParticleSystem;
Класс PSBehavior;
Класс
PSAcceleration;
Класс
PSDeceleration;
Класс PSKillOld;
Класс
PSSizeController;
Класс
PSColorController;
Класс PSElastic;
Класс
PSActionObject;
Класс PSPoint;
Класс PSPlane;
Класс
PSRectangle;
Класс PSCircle;
Класс PSSphere;
Класс Emitter;
Класс
EmitterRepeater;
Класс
EmitterSingleShoot.
Класс Particle
Класс Particle (рис. 5.1) хранит сведения о
частице, такие как позиция, скорость, цвет, размер, время жизни.
Рисунок 5.1 - Диаграмма класса Particle
Также содержит метод GetVirtices, который
возвращает список вершин для отрисовки примитива, который представляет частицу
в трехмерном пространстве.
Класс Particle System
Основным классом библиотеки является класс
ParticleSystem (рисунок 5.2). Он хранит список «живых» частиц и настройки для
моделирования и отрисовки частиц.
Рисунок 5.2 - Диаграмма класса Particle System
библиотека частица графика шейдер
ParticleSystem наследуется от класса
DrowableGameComponent библиотеки XNA, что упрощает и ускоряет интеграцию
системы в приложения XNA.
В качестве основных настроек моделирования класс
ParticleSystem использует список объектов класса PSBehavior. Комбинируя разные
объекты классов наследников PSBehavior с разными параметрами можно получить
разные по характеристикам эффекты.
Для настройки параметров отображения
используются поля BlendState и Texture, которые задают способ смешивания
текстур и саму текстуру, которая накладывается на биллборд.
Класс PSBehavior и его наследники
Класс PSBehavior (рисунок 5.3) объявляет общий
интерфейс, а его наследники производят необходимые манипуляции над частицей при
помощи метода Update. В метод Update передаются частица, над которой необходимо
произвести некоторое действие, и время, прошедшее с момента прошлого изменения.
Объект класса PSAcceleration (рисунок 5.3)
ускоряет частицу в направлении dir.
Листинг 5.1 - Реализация метода Update класса
PSAcceleration
public override void Update(ref
Particle part, float elepsedTime)
{.velocity += dir * elepsedTime;
}
Объект класса
PSDeceleration (рисунок
5.3) замедляет
частицу,
умножая
каждый
компонент
вектора
скорости
на
коэффициент
k, если
скорость
находится
в
пределах
vlow и
vhight.
Листинг 5.2 - Реализация метода Update класса
PSDeceleration
public override void Update(ref
Particle part, float elepsedTime)
{length =
part.velocity.Length();(length > vlow && length < vhight)
{norm = 1 - (1 - k) *
elepsedTime;.velocity *= norm;
}
}
Замечание: так как на коэффициент k нет
ограничений, то значения больше 1.0 приводит к ускорению частиц в k раз.
Объект класса PSKillOld (рисунок 5.3) изменяет
состояние частицы alive, если ее продолжительность жизни больше duration.
Листинг 5.3 - Реализация метода Update класса
PSKillOld
public override void Update(ref
Particle part, float elepsedTime)
{(part.lifetime >=
duration).alive = false;
}
Объект класса PSSizeController (рисунок 5.3)
изменяет размер частицы с текущего до targetsize, в промежутке времени жизни от
from до to. Для расчета промежуточных значений размера используется линейная
интерполяция. Ясно, что чем меньше разница между начальным значением размера и
конечным, и длиннее промежуток времени, тем более плавное изменение размера
будет производиться.
Листинг 5.4 - Реализация метода Update класса
PSSizeController
public override void Update(ref
Particle part, float elepsedTime)
{(part.lifetime > from &&
part.lifetime < to)
{timeLeft = to -
part.lifetime;sizeNeed = targetSize - part.size;.size += sizeNeed * elepsedTime
/ timeLeft;
}
}
Объект класса
PSTargetController (рисунок
5.3) изменяет
цвет
частицы
с
текущего
до
targetcolor, в промежутке
времени
жизни
от
from до
to. Принцип
работы точно такой же, как в описанном выше PSSizeController.
Листинг 5.5 - Реализация метода Update класса
PSTargetController
public override void Update(ref
Particle part, float elepsedTime)
{(part.lifetime > from &&
part.lifetime < to)
{pColor =
part.color.ToVector4();timeLeft = to - part.lifetime;colorNeed = targetColor -
pColor;+=colorNeed * elepsedTime / timeLeft;.color = new Color(pColor);
}
}
Объект класса PSElastic (рисунок 5.3) проверяет
частицы на столкновение с поверхностью объекта surface класса PSActionObject.
При столкновении вектор скорости частицы раскладывается на нормальную (5.1)
и тангенциальную (5.2)
составляющие.
, (5.1)
(5.2)
|
|
Рисунок 5.4 - Разложение вектора скорости.
Коэффициент friction масштабирует тангенциальную
составляющую, а restitution - отраженную нормальную составляющую. В результате
получаем новую скорость частицы (5.3)[5].
,(5.3)
|
|
Рисунок 5.5 - Расчет нового вектора скорости
Листинг 5.6 - Реализация метода Update класса
PSElastic
public override void Update(ref
Particle part, float elepsedTime)
{normal;epsilon =
part.velocity.Length() * elepsedTime;(surface.Collision(part.position,<
0.05f ? 0.05f : epsilon,normal))
{= Vector3.Dot(part.velocity,
normal) * normal;tangent = part.velocity - normal;.velocity = -normal *
restitution;(tangent.Length() > minvelocity).velocity += tangent *
friction;.velocity += tangent;
}
}
Класс PSActionObject и его наследники
Объекты класса PSActionObject (рисунок 5.6)
представляют область в пространстве. Эти объекты можно использовать для
создания частиц и для проверки столкновения c частицами при помощи методов
GetRandomPoint и Collision. Метод GetRandomPoint возвращает случайную точку из
области пространства. Метод Collision возвращает истину, если точка принадлежит
области с погрешностью epsilon, и возвращает нормаль к поверхности в этой
точке.
Рисунок 5.6 - Диаграмма классов PSActionObject
Объект PSPoint (рисунок 5.6) представляет собой
точку в пространстве.
Объект PSPlane (рисунок 5.6) представляет собой
плоскость в пространстве. Плоскость определяется точкой origin и нормалью к
плоскости normal.
Метод генерации случайных точек генерирует точки
в заданной точке origin.
Проверка столкновения производится следующим
образом (рисунок 5.4.2.1):
Находим вектор от точки на плоскости до частицы.
Находим проекцию вектора найденного в первом
пункте на нормаль.
Если длина проекции меньше погрешности epsilon
(формула 5.4), то столкновение[5].
,(5.4)
|
|
Рисунок 5.7 - Проверка столкновения
Объект класса PSRectangle (рисунок 5.6)
представляет собой параллелепипед в пространстве. Параллелепипед задается
точкой в пространстве origin и двумя векторами u и v, которые указывают
направление и длину ребер.
В проверке столкновений в отличии от PSPlane
добавляются дополнительные проверки:
Находятся проекции на ребра u и v.
Если длины проекций меньше длин ребер, то
столкновение.
Объект класса PSCircle (рисунок 5.6)
представляет собой круг в пространстве. Круг задается точкой origin в пространстве,
нормалью к плоскости в которой лежит круг, внешним радиусом и внутренним
радиусом.
В проверке столкновений в отличии от PSPlane
добавляются еще один шаг:
Если длина вектора лежит
в диапазоне от внутреннего радиуса до внешнего, то столкновение.
Объект класса PSSphere (рисунок 5.6)
представляет собой сферу в пространстве. Сфера задается точкой origin в
пространстве, внешним радиусом и внутренним радиусом.
Проверка столкновения производится следующим
образом: если расстояние от точки origin до частицы не меньше внутреннего и не
больше внешнего радиусов, то столкновение.
Класс Emitter описывает излучатель частиц
(рисунок 5.8). Излучатель необходим для автоматизации и упрощения процесса
генерирование новых частиц и добавление их в систему частиц ParticleSystem.
Класс Emitter также наследуется от класса GameComponent библиотеки XNA, что
упрощает и ускоряет интеграцию излучателя в приложение XNA.
Рисунок 5.8 - Диаграмма классов Emitter
Класс эмиттера содержит следующие поля для
управления генерацией частиц:устанавливает начальный диапазон вертикальной
скорости.устанавливает начальный диапазон горизонтальной скорости.устанавливает
начальный диапазон размера частиц.- устанавливает первую границу начального
диапазона цвета частиц.- устанавливает вторую границу начального диапазона
цвета частиц.
Метод GenerateParticle создает частицу в
зависимости от вышеописанных параметров.
Метод Update вызывает метод GenerateParticle и
добавляет созданную частицу в ParticleSystem.
Методы Start и Stop запускают и останавливают
эмиттер соответственно.
Данная реализация излучателя (рисунок 5.8)
выпускает particlePerSecond частиц в секунду, пока излучатель запущен.
Листинг 5.7 - Реализация метода Update класса
EmitterRepeater
public override void Update(GameTime
gameTime)
{elepsedTime =
(float)gameTime.ElapsedGameTime.TotalSeconds;+= elepsedTime;(timeLeftOver >
timeBetweenPrticle)
{.AddParticle(GenerateParticle());-=
timeBetweenPrticle;
}
}
Данная реализация излучателя (рисунок 5.8)
выпускает particlePerShoot частиц при запуске и сразу же останавливается.
Листинг 5.8 - Реализация метода Update класса
EmitterSingleShoot
public override void Update(GameTime
gameTime)
{(int i = 0; i<particlePerShoot;
i++)
{.AddParticle(GenerateParticle());
}
();
}
Руководство пользователя
Подключение библиотеки
Для того чтоб использовать библиотеку в своем
проекте необходимо подключить ее. Библиотека скомпилирована в dll файл, что
упрощает ее подключение:
Вам только нужно в своем проекте указать ссылку
на dll файл.
Рисунок 6.1 - Добавление ссылки
Рисунок 6.2 - Выбор dll файла библиотеки
И подключить пространство имен
ParticleSystemLibrary.
Листинг 6.1 - Подключение пространства имен
ParticleSystemLibraryMicrosoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;Microsoft.Xna.Framework.Media;
using ParticleSystemLibrary;
Создание, настройка и подключение системы частиц
Создаем объект класса ParticleSystem.
Листинг 6.2 - Создание объекта класса
ParticleSystem= new ParticleSystem(this);
Подключаем объекты поведения, чтобы придать
необходимое поведение нашей системе.
Листинг 6.3 - Настройка
объекта
класса
ParticleSystem.AddBehavior(new PSAcceleration(new Vector3(0, -15,
0)));.AddBehavior(new PSElastic((new Vector3(0, 0, 0), new Vector3(0, 1, 0),
20),
.3f,
.9f,
f));.AddBehavior(new PSKillOld(6));
Далее необходимо подключить объект класса
ParticleSystem к компонентам класса владельца (в нашем случае класса Game1).
Листинг 6.4 - Подключение объекта класса
ParticleSystem.Components.Add(fountainPS);
И в заключении необходимо в методе Drow класса
владельца вызвать метод SetCamera объекта класса ParticleSystem, чтобы передать
матрицы вида и проекции, в противном случае система частиц не будет отображать
частицы.
Листинг 6.5 - Установка
камерыoverride
void Draw(GameTime gameTime)
{.Clear(Color.Black);.SetCamera(camera.view,
camera.projecton);
base.Draw(gameTime);
}
Создание, настройка и подключение излучателя
Создаем объект класса Emitter.
Листинг 6.6 - Создание объекта класса Emitter
fountainEmitter = new EmitterRepeater(this,
fountainPS, 300, new PSPoint(new Vector3(0, 1, 0)));
Устанавливаем начальные значения для
генерируемых частиц.
Листинг 6.7 - Настройки
объекта
класса
Emitter.StartHorizontalVelocity = Vector2(1f,2f);.StartVerticalVelocity =
Vector2(20f,22f);.StartColorMin = .AliceBlue.ToVector4();.StartColorMax =
Color.Blue.ToVector4();
Подключаем объект к компонентам класса владельца
(в нашем случае класса Game1.
Листинг 6.8 - Подключение объекта класса
Emitter.Components.Add(fountainEmitter);
Результат
В результате вышеописанных действий мы получим
систему частиц, которая моделирует работу фонтана (рисунок 6.3).
Рисунок 6.3 - Результат
Заключение
В результате данного дипломного проекта была
разработана библиотека, позволяющая начинающим разработчикам игр с легкостью
использовать такое средство как система частиц, для добавления эффектов в свои
проекты.
На данный момент в библиотеке имеется 18
классов. Из которых 13 наследуются от 3 классов и имеют общий интерфейс с этими
классами. Поэтому для освоения данной библиотеки, т.е. изучения возможностей
каждого класса, не требуется много времени.
Библиотека написана на платформе .NET для
графической библиотеки XNA. Таким образом, для применения библиотеки необходимо
изучить один из языков платформы .NET (С# и т.д.) и библиотеку XNA, что намного
быстрее, чем изучать C++ и DirectX или OpenGL.
Эффективность библиотеки зависит от частоты
тактового процессора и падает с ростом числа отображаемых частиц. При испытании
библиотеки на персональном компьютере с частотой 2.1 ГГц максимальное число
частиц, при отображении которых получалась приемлемая частота кадров (30FPS),
составила 2000. Для отображения эффекта дыма в демонстрационных примерах
потребовалось 250 частиц.
При создании библиотеки активно использовались
принципы ООП наследование и полиморфизм, что обеспечило библиотеку необходимой
гибкостью и расширяемостью. Для расширения возможностей существует 3
абстрактных класса Emitter, PSBehavior, PSActionObject, от которых можно наследовать
создаваемые пользовательские классы.
В дальнейшем проект можно совершенствовать,
добавляя новые возможности в моделировании частиц, расширять функциональность,
как например проверка столкновений и притяжение между частицами. Также можно
совершенствовать и оптимизировать уже существующие алгоритмы, для повышения
производительности, точности, графики. Так за счет усложнения математической и
физической составляющей библиотека может использоваться для научных
моделирований.
Литература
Теория
статистики с основами теории вероятностей. Учебник./Под ред. И.Елисеевой.- М.:
ЮНИТИ - ДАНА,2011- 446 с.
Основы
математической статистики. Под ред. А.П. Зинченко. - М: МСХА .- 2012.-154с.
Практикум
по математической статистике. Под ред. О.Б. Тарасовой. М.РГАУ-МСХА. 2009.-137с.
Гатаулин
А.М.: Учебное пособие. Система прикладных статистико-математических методов
обработки экспериментальных данных в сельском хозяйстве.- М.:МСХА,1992 (ч.1 и
2)
Баканов
М.И., Шеремет А.Д. Теория экономического анализа. - М.: Финансы и статистика,
2009. -416 с.
Практикум
по статистике. Учебное пособие. Зинченко А.П., Шибалкин А.Е., Тарасова О.Б.,
Шайкина Е.В. -М.: Колос, 2001.-392с. КолосС 2003, 2004, 2007.
Чернова
Т.В. Экономическая статистика Учебное пособие. Таганрог: Изд-во ТРТУ, 2012
Моисеева
Т.М.статья "Мониторинг состояния экономических объектов"