Difference between revisions of "Basic Concept"
(3 intermediate revisions by the same user not shown) | |||
Line 3: | Line 3: | ||
<translate> | <translate> | ||
<!--T:1--> | <!--T:1--> | ||
− | В статье описаны основные решения, используемые в W4 Game Engine | + | В статье описаны основные решения, используемые в W4 Game Engine: |
+ | * Координатная истема | ||
+ | * Нодовая система | ||
+ | * API основных классов | ||
</translate> | </translate> | ||
+ | |||
== Coordinate System == | == Coordinate System == | ||
[[File:Concept 01.png|thumb|<translate><!--T:2--> Координатная система</translate>]] <translate><!--T:3--> Используется [https://en.wikipedia.org/wiki/Cartesian_coordinate_system#In_three_dimensions left-handed координатная система] и вращение производится против часовой стрелки, если смотреть в направлении оси.</translate> | [[File:Concept 01.png|thumb|<translate><!--T:2--> Координатная система</translate>]] <translate><!--T:3--> Используется [https://en.wikipedia.org/wiki/Cartesian_coordinate_system#In_three_dimensions left-handed координатная система] и вращение производится против часовой стрелки, если смотреть в направлении оси.</translate> | ||
Line 76: | Line 80: | ||
| <syntaxhighlight lang="c++">void traversal(const Callback&) | | <syntaxhighlight lang="c++">void traversal(const Callback&) | ||
− | + | void traversal(const PredicateC & predicate, const Callback&) | |
template<typename T> void traversalTyped(const std::function<void(w4::cref<T>)>&);</syntaxhighlight> || <translate><!--T:19--> Выполнение функтора начиная с текущего узла и вниз по иерархии. </translate> | template<typename T> void traversalTyped(const std::function<void(w4::cref<T>)>&);</syntaxhighlight> || <translate><!--T:19--> Выполнение функтора начиная с текущего узла и вниз по иерархии. </translate> | ||
Line 284: | Line 288: | ||
//<translate><!--T:52--> добавляем спутник как "ребёнка" орбиты</translate> | //<translate><!--T:52--> добавляем спутник как "ребёнка" орбиты</translate> | ||
orbitContainer->addChild(moonNode); | orbitContainer->addChild(moonNode); | ||
− | //<translate><!--T:53--> устанавливаем позицию | + | //<translate><!--T:53--> устанавливаем позицию тела на орбите</translate> |
moonNode->setLocalTranslation({moon.m_orbit, 0, 0}); | moonNode->setLocalTranslation({moon.m_orbit, 0, 0}); | ||
moonNode->getMaterialInst()->setParam("baseColor", moon.m_color); | moonNode->getMaterialInst()->setParam("baseColor", moon.m_color); | ||
Line 521: | Line 525: | ||
==== ParticlesEmitter ==== | ==== ParticlesEmitter ==== | ||
− | <translate> | + | <translate> |
− | |||
− | |||
<!--T:127--> | <!--T:127--> | ||
Особенности: | Особенности: |
Latest revision as of 13:55, 19 June 2020
Contents
Scope
В статье описаны основные решения, используемые в W4 Game Engine:
- Координатная истема
- Нодовая система
- API основных классов
Coordinate System
Используется left-handed координатная система и вращение производится против часовой стрелки, если смотреть в направлении оси.
Render Tree
Отображаемый на экране результат и зависимость трансформаций объектов друг от друга определяются деревом рендеринга, то есть набором объектов рендеринга. Особенности дерева рендеринга W4 Game Engine:
- Минимальное дерево рендеринга состоит только из корневого узла.
- У каждого узла может быть ноль или более подузлов — «детей», но при этом у узла не может быть более одного “родителя“ (самый верхний узел - “корневой“ - родителя не имеет).
- Для того чтобы объект отобразился на экране и/или пересчитал свои данные, необходимо чтобы он находился в дереве.
- Иерархия встроенных типов узлов показана на схеме.
Назначение и интерфейсы узлов (классов) описаны в следующих параграфах.
Примечания по использованию:
- При рисовании в несколько проходов, у каждого прохода создаётся своё дерево со своим корневым узлом.
- У каждого узла можно узнать локальные трансформации (то есть трансформации относительно “родителя“) и мировые, а также задать их.
- При задании мировых координат узла пересчитываются его локальные координаты, при задании локальных - мировые.
- У узла, не имеющего родителя трансформации совпадают.
- Можно временно отключить узел, при этом отключаются и все его “потомки“.
Node
Node - базовый класс любого узла (в том числе RootNode).
Method | Description |
---|---|
w4::sptr<render::RootNode> getRoot() const
|
Возвращает корневой узел дерева или nullptr при её отсутствии |
w4::sptr<Node> clone() const
|
Создаёт копию узла, но не имеющую “родителя“ |
w4::sptr<Node> getParent() const
|
Возвращает “родительский“ узел или nullptr при его отсутствии |
void setEnabled(bool)
|
Включает/выключает узел и его “потомков“ |
void addChild(w4::cref<Node>, bool preserveTransorm = true)
void addChild(const std::string&, w4::cref<Node>, bool preserveTransorm = true)
|
Добавляет “детей“ к текущему узлу. Возможно задание имени для “ребёнка“.
Параметр "preserveTransform" определяет локальные(false) или глобальные(true) трансформации, которые сохраняются у “ребёнка“. Например, если дополнить код слева строками: childNode->setLocalTranslation({1, 0, 0});
parentNode->addChild(childNode);
то узел childNode будет находиться в мировой позиции {1, 0, 0}, а если использовать следующие строки: childNode->setLocalTranslation({1, 0, 0});
parentNode->addChild(childNode, false);
то узел childNode будет сдвинут на 1 по оси X относительно родителя. |
void removeChild(w4::cref<Node>)
void removeChild(const std::string&)
void removeChild(const std::list<w4::sptr<Node>>&)
|
Отвязка “детей“ от узла по указателю, имени и списку. |
void traversal(const Callback&)
void traversal(const PredicateC & predicate, const Callback&)
template<typename T> void traversalTyped(const std::function<void(w4::cref<T>)>&);
|
Выполнение функтора начиная с текущего узла и вниз по иерархии.
Callback имеет сигнатуру void(Node&) PredicateC - bool(w4::core::Node&) Последний метод вызывает функтор только для тех узлов, чей тип унаследован от T |
void setWorldRotation(math::Rotator::cref, math::vec3::cref worldPt)
|
Установка поворота относительно точки в мировых координатах |
void rotateAroundPoint(const math::Rotator& rotator, const math::vec3& worldPt)
|
Вращение вокруг точки в мировых координатах |
template<typename T> w4::sptr<T> as()
template<typename T> w4::sptr<const T> as() const
template<typename T> T* asRaw()
template<typename T> const T* asRaw() const
|
Приведение типа узла (прим. указываемый тип не проверяется) |
template<typename T> bool derived_from() const
|
Проверка, является ли класс узла потомком заданного класса |
template<typename T> w4::sptr<T> getChild(const std::string&)
|
Получение ”ребёнка” по имени с приведением типа (прим. указываемый тип не проверяется) |
std::list<w4::sptr<Node>> getAllChildren() const
|
Получение списка всех узлов, находящихся ниже по иерархии (“дети“, “дети детей“…) |
std::list<w4::sptr<Node>> findChildren(std::string const&) const
|
Поиск “ребёнка“ по имени |
std::list<w4::sptr<Node>> findChildrenRecursive(std::string const&) const
|
Поиск вниз по иерархии по имени |
math::vec3::cref getWorldTranslation() const
void setWorldTranslation(math::vec3::cref)
math::vec3::cref getLocalTranslation() const
void setLocalTranslation(math::vec3::cref)
|
Получение и установка позиции в мировых или локальных координатах |
math::vec3::cref getWorldScale() const
void setWorldScale(math::vec3::cref)
math::vec3::cref getLocalScale() const
void setLocalScale(math::vec3::cref)
|
Получение и установка масштаба в мировых или локальных координатах |
math::vec3 getWorldUp() const
math::vec3 getWorldForward() const
math::vec3 getWorldRight() const
|
Получение нормализованных векторов в направлениях вверх, вперёд и вправо пространства модели в мировых координатах |
math::Transform::cref getWorldTransform() const
void setWorldTransform(math::Transform::cref)
math::Transform::cref getLocalTransform() const
void setLocalTransform(math::Transform::cref)
|
Получение и установка трансформации в мировых или локальных координатах. Трансформация - сочетание позиции, поворота и масштаба |
math::Rotator::cref getWorldRotation() const
void setWorldRotation(math::Rotator::cref)
math::Rotator::cref getLocalRotation() const
void setLocalRotation(math::Rotator::cref)
void rotateLocal(const math::Rotator&rotator)
void rotateWorld(const math::Rotator&rotator)
|
Получение и установка поворота в мировых или локальных координатах. Методы rotateWorld/Local добавляют поворот к текущим значениям |
const std::unordered_set<w4::sptr<Node>>& getChildren() const
|
Получение списка “детей“ |
bool isEnabled() const
|
Возвращает, включен ли узел |
bool hasParent() const
|
Возвращает имеет ли узел “родителя“ |
Hierarchy Example
Возьмём реальные астрономические цифры и построим упрощённую модель солнечной системы. Так как используются космические расстояния, обозреть всю систему не представляется возможным (хотя ничего не мешает попробовать сделать модель более наглядной). В данном случае, модель взята не для визуализации, а для примера возможностей иерархии и вложенности трансформов.
#include "W4Framework.h"
W4_USE_UNSTRICT_INTERFACE
class Planet
{
public:
//Немного данных о небесном теле:
// - имя
// - цвет
// - радиус (км)
// - радиус орбиты (км)
// - период оборота вокруг главного тела (дней)
// - угол отклонения орбиты относительно плоскости обращения вокруг главного тела
// - наклон оси
// - список спутников
Planet(const std::string& name, const color& planetColor, float planetRadius, float planetOrbit, float siderealPeriod, float eclipseAngle, float axisTilt, const std::vector<Planet>& moons)
: m_color(planetColor),
m_radius(planetRadius),
m_orbit(planetOrbit),
m_siderealPeriod(siderealPeriod),
m_eclipseAngle(eclipseAngle),
m_axisTilt(axisTilt),
m_moons(moons)
{}
color m_color;
float m_radius;
float m_orbit;
float m_siderealPeriod;
float m_eclipseAngle;
float m_axisTilt;
std::vector<Planet> m_moons;
};
struct SolarDemo : public IGame
{
public:
void onStart() override
{
//на старте создаём солнечную систему
createSolarSystem();
}
void onMove(const event::Touch::Move& evt)
{
}
void onUpdate(float dt) override
{
for(auto& rotation: m_rotations)
{
//вращаем тела вокруг их главных тел со скоростью 0.5 дня в секунду
rotation.first->rotateLocal(rotation.second * (dt / 2));
}
}
private:
void createSolarSystem()
{
// вот она - Солнечная система!
const Planet solarSystem("Sun", color::yellow, 695500.f, 0.f, 345.39f, 0.f, 0.f, {
{"Mercury", color::white, 2439.7f, 57909050.f, .241f, 7.01f, .0352f, {}},
{"Venus", color::magenta, 6051.8f, 108208000.f, .615, 3.39f, 177.36f, {}},
{"Earth", color::green, 6378.f, 149598261.f, 1.f, 0.f, 23.44f, {
{"Moon", color::gray, 1737.1f, 384399.f, 1.f, 0.f, 0.f, {}}
}},
{"Mars", color::red, 3393.5f, 227939100.f, 1.88f, 1.85f, 25.19f, {
{"Phobos", color::gray, 11.2667f, 9377.2f, .317f, 1.093f, 0.f, {}},
{"Demos", color::gray, 10.f, 23458.f, 1.2625f, 1.85f , 0.f, {}}
}},
{"Jupiter", color(1.f, .5f, 0.f, 1.f), 71400.f, 778547200.f, 11.86f, 1.31f, 3.13f, {
{"Callisto", color::gray, 2410.3f, 1882709.f, 16.69f, .205f, 0.f, {}},
{"Europa", color::gray, 1560.8f, 671034.f, 3.55f, .471f, 0.f, {}},
{"Ganymede", color::gray, 2634.1f, 1070412.f, 7.15f, .204f, 0.f, {}},
{"Io", color::gray, 1818.f, 421700.f, 1.77f, .05f, 0.f, {}}
}},
{"Saturn", (color::yellow + color::white) / 2, 60000.f, 1433449370.f, 29.46f, 2.49f, 26.73f, {
{"Dione", color::gray, 560.f, 377415.f, 2.74f, .028f, 0.f, {}},
{"Enceladus", color::gray, 251.4f, 238042.f, 1.370218f, 0.f, 0.f, {}},
{"Tethys", color::gray, 530.f, 294672.f, 1.887802f, 1.091f, 0.f, {}},
{"Titan", color::gray, 2575.f, 1221865.f, 15.945f, .306f, 0.f, {}}
}},
{"Uranus", color::cyan, 25600.f, 2876679082.f, 84.01f, .77f, 97.77f, {
{"Ariel", color::gray, 578.9f, 191020.f, 2.520379f, .26f, 0.f, {}},
{"Oberon", color::gray, 761.4f, 583520.f, 13.463239f, .058f, 0.f, {}},
{"Titania", color::gray, 588.9f, 435910.f, 8.705872f, .34f , 0.f, {}},
{"Umbriel", color::gray, 584.7f, 266300.f, 4.144177f, .205f, 0.f, {}}
}},
{"Neptune", color::blue, 24300.f, 4503443661.f, 164.79f, 1.77f, 28.32f, {
{"Triton", color::gray, 1353.4, 4503443661.f, 164.79f, 1.77f, 0.f, {}}
}}
});
//Создаём Солнце
auto sun = Mesh::create::sphere(solarSystem.m_radius, 10, 10);
//Добавляем его в корневой узел
Render::getRoot()->addChild(sun);
//Устанавливаем цвет для базового материала
sun->getMaterialInst()->setParam("baseColor", solarSystem.m_color);
//Создаём планеты
createMoons(sun, solarSystem);
//Устанавливаем масштаб. Увы, расстояния такие, что с реальными расстояниями без лупы видно только Солнце... Но это пример.
sun->setLocalScale({1.e-7f, 1.e-7f, 1.e-7f});
}
void createMoons(cref<Node> planetNode, const Planet& planet)
{
//для каждого спутника
for(const auto& moon: planet.m_moons)
{
//для иллюстрации вложенности - создадим узел - орбиту, при вращении которого вокруг центра тело будет передвигаться по орбите
auto orbitContainer = make::sptr<Node>();
//отклоняем орбиту от плоскости вращения главного тела
orbitContainer->setLocalRotation({(planet.m_axisTilt + moon.m_eclipseAngle) * DEG2RAD, 0, 0});
//создаём тело
auto moonNode = Mesh::create::sphere(moon.m_radius, 10, 10);
//добавляем спутник как "ребёнка" орбиты
orbitContainer->addChild(moonNode);
//устанавливаем позицию тела на орбите
moonNode->setLocalTranslation({moon.m_orbit, 0, 0});
moonNode->getMaterialInst()->setParam("baseColor", moon.m_color);
//добавляем орбиту как "ребёнка" главного тела. Особое внимание на параметр false - он обозначает,
//что при чайлдинге сохраняются локальные трансформы. Таким образом, орбита окажется в той же позиции,
//что и планета и наклонена относительно его плоскости обращения
planetNode->addChild(orbitContainer, false);
//рекурсивно создаём спутники
createMoons(moonNode, moon);
//добавляем в список орбиты и кватернионы для их поворота в локальном пространстве (вычисляем из углов эйлера)
m_rotations.emplace_back(orbitContainer, Rotator(0, 0, 1 / moon.m_siderealPeriod));
}
}
std::vector<std::pair<sptr<Node>, Rotator>> m_rotations;
};
W4_RUN(SolarDemo)
VisibleNode
Базовый класс для отображаемого узла.
Особенности:
- Все отображаемые узлы содержат вертексный буфер и состоят из одного и более элемента surface (который содержит индексный буфер).
- Каждому surface можно назначить свой материал.
Все отображаемые узлы имеют следующие дополнительные методы:
Method | Description |
---|---|
const MaterialInstPtr& getMaterialInst(const std::string& surfaceName) const
|
Возвращает материал указанного surface |
const MaterialInstPtr& getMaterialInst() const
|
Получает материал, установленный для всех surface. Если материалы surface отличаются - выдаёт ошибку в лог и возвращает какой-то материал. |
void setMaterialInst(const MaterialInstPtr & m)
|
Устанавливает материал для всех surface |
Mesh
Объект, отображающий геометрию.
Объекты типа Mesh в движке можно создать тремя путями: 1. Загрузить из ресурсов (см. также Mesh Converter):
teapot = Asset::load(Path("resources/teapot", "teapot.asset"))->getRoot()->getChild<Mesh>("Utah Teapot Quads");
2. Вызвать встроенный генератор:
auto sphere = Mesh::create::sphere(радиус, количество параллелей, количество меридианов);
auto box = Mesh::create::box({width, height, depth}); //box - параллелепипед, у которого каждая грань - surface
auto cube = Mesh::create::cube({width, height, depth});
auto mappedCube = Mesh::create::mappedCube({width, height, depth}); //параллелепипед с uv координатами под развёртку
auto plane1 = Mesh::create::plane({width, height}, scaleUv); //плоскость по осям XY. scaleUv = false(по умолчанию) - UV от 0 до 1, true - от 0 до ширины/высоты
auto plane2 = Mesh::create::plane({left, down}, {right, up}, scaleUv; //то же самое
auto cylinder = Mesh::create::cylinder(высота, радиус, количество секторов);
auto cone = Mesh::create::cone(верхний радиус, нижний радиус, высота, количество секторов, количество сегментов по вертикали);
auto torus = Mesh::create::torus(радиус кольца, радиус "трубы", количество сегментов кольца, количество сегментов "трубы", угол дуги кольца(2*PI для замкнутого тора));
auto skybox = Mesh::create::skybox(); //Скайбокс. Единичный куб со сторонами, отображаемыми изнутри.
3. Создать из кода:
auto indicesBuf = make::sptr<UserIndicesBuffer>("Floor indices");
auto verticesBuf = make::sptr<UserVerticesBuffer<Mesh::VertexFormat>>("floor_" + std::to_string(width) + "x" + std::to_string(height) + "-" + std::to_string(offset));
indicesBuf->setNeedExport(false);
verticesBuf->setNeedExport(false);
resources::MeshVertexDataBuilder vdb(verticesBuf, indicesBuf);
//позиция, UV, нормаль
vdb.addVertex({-width / 2 + offset, 0, height / 2}, {offset/width, 0.f}, {0, 1, 0});
vdb.addVertex({width / 2 - offset, 0, height / 2}, {1.f - offset/width, 0.f}, {0, 1, 0});
vdb.addVertex({-width / 2, 0, height / 2 - offset}, {0.f, offset/height}, {0, 1, 0});
vdb.addVertex({width / 2, 0, height / 2 - offset}, {1.f, offset/height}, {0, 1, 0});
vdb.addVertex({width / 2, 0, -height / 2 + offset}, {0.f, 1.f - offset/height}, {0, 1, 0});
vdb.addVertex({-width / 2, 0, -height / 2 + offset}, {1.f, 1.f - offset/height}, {0, 1, 0});
vdb.addVertex({width / 2 - offset, 0, -height / 2}, {offset/width, 1.f}, {0, 1, 0});
vdb.addVertex({-width / 2 + offset, 0, -height / 2}, {1.f - offset/width, 1.f}, {0, 1, 0});
vdb.addIndices({2, 1, 0,
2, 3, 1,
4, 3 ,2,
5, 4, 2,
5, 6, 4,
7, 6, 5});
vdb.build();
auto result = make::sptr<Mesh>(verticesBuf->getName(), verticesBuf);
result->addComponent<Surface>("unnamed", indicesBuf);
result->setMaterialInst(Material::getDefault()->createInstance());
SkinnedMesh
Объект, отображающий геометрию с анимацией.
Особенности:
- можно загрузить только из файла;
- представляет собой геометрию со скелетной анимацией;
- содержит в себе набор анимаций;
- содержит в себе API для управления анимациями и позволяет проигрывать несколько анимаций с плавными переходами между ними.
Method | Description |
---|---|
w4::cref<core::Node> createSocket(const std::string& boneName)
|
Создаёт узел для крепления на кости с заданным именем. К этому узлу можно добавлять “детей“ |
w4::cref<core::Node> getSocket(const std::string& boneName) const
|
Возвращает узел для крепления на кости с заданным именем |
std::vector<std::string> getAvailableAnimations() const
|
Возвращает список имеющихся анимаций |
bool haveAnimation(const std::string& animationName) const
|
Проверяет наличие анимации с заданным именем |
size_t getAnimationIndex(const std::string& animationName) const
|
Получение индекса анимации по её имени |
const std::string& getAnimationName(size_t animationIndex) const
|
Получение имени анимации по её индексу |
void setAnimationStateChangedCallback(std::function<void(Animator&, Animator::State)>)
void setAnimationStateChangedCallback(Animator::State, std::function<void(Animator&)>)
|
Установить функтор, который вызовется по изменению состояния конкретной анимации. Метод имеет как вариант только для заданного состояния, так и для любого. Состояния анимаций:
Animator::State::Idle(не проигрывается/закончилась), Animator::State::Play(проигрывается), Animator::State::Pause(приостановлена) Пример: node->setAnimationStateChangedCallback(Animator::State::Idle, [](Animator& animator)
{
W4_LOG_DEBUG("Animator stopped:\n"
"\tName: %s,"
"\tSpeed: %f,"
"\tDuration: %f,"
"\tFps: %f",
animator.getName().c_str(),
animator.getSpeed(),
animator.getDuration(),
animator.getFps());
});
|
void play(const std::string& animationName, float duration = 0.f)
void play(size_t animationIndex = 0, float duration = 0.f)
|
Проигрывание анимации по индексу или имени. Указывается длительность анимации, если она равна нулю - проигрывается анимация целиком |
void play(std::initializer_list<std::pair<std::string, float>>, float duration = 0.f)
void play(std::initializer_list<std::pair<size_t, float>>, float duration = 0.f)
|
Проигрывание списка анимаций с весами. Длительность, если равна нулю - равна анимации с максимальной длительностью
Пример: skinned->play({{"run", .3f}, {"jump", .7f}});
|
void pause()
|
Приостановить все активные анимации |
void resume()
|
Возобновить проигрывание всех приостановленных анимаций |
void stop()
|
Остановить проигрывание всех активных анимаций |
bool isPlaying() const
|
Проверяет, проигрывается ли сейчас любая анимация |
Animator & getAnimator(size_t)
Animator & getAnimator(const std::string&)
const Animator & getAnimator(size_t) const
const Animator & getAnimator(const std::string&) const
|
Получить объект аниматор по имени или индексу. API объекта Animator описан чуть ниже. Используется для управления анимациями с расширенными возможностями.
Управление анимациями через API и SkinnedMesh не являются взаимоисключающими. Так, например, общеупотребительной является практика зацикливания анимаций: m_skinned->getAnimator("dance").setIsLooped(true);
|
Animator API
Method | Description |
---|---|
void play()
|
Запуск воспроизведения анимации.
В случае, если она уже проигрывается, она будет остановлена и запущена с начала |
void pause()
|
Приостанавливает воспроизведение анимации |
void resume()
|
Возобновляет воспроизведение анимации |
void stop()
|
Останавливает воспроизведение анимации |
void seek(float targetTime)
|
Устанавливает текущую позицию в анимации на заданное время. Значения автоматически обрезаются сверху и снизу до диапазона [0; длина анимации] или до диапазона, заданного методами setBeginTime/setEndTime |
bool isLooped() const
|
Возвращает, включен ли для данной анимации режим циклическое воспроизведение |
float getSpeed() const
|
Получает множитель скорости воспроизведения анимации (по умолчанию 1.0) |
State getState() const
|
Возвращает состояние анимации
Состояния анимаций: Animator::State::Idle (не проигрывается/закончилась), Animator::State::Play (проигрывается), Animator::State::Pause (приостановлена) |
void setPlayType(PlayType)
|
Устанавливает направление воспроизведения.
Возможные значения параметра: Animator::PlayType::Forward (вперёд), Animator::PlayType::Backward (в обратном направлении) |
PlayType getPlayType() const
|
Возвращает текущее направление проигрывания. Возможные значения см. в setPlayType |
float getCurrentTime() const
|
Возвращает текущую позицию в анимации |
void setIsLooped(bool)
|
Включает/выключает для данной анимации режим циклического воспроизведение |
void setSpeed(float)
|
Устанавливает множитель скорости воспроизведения анимации |
void setBeginTime(float)
|
Устанавливает начальное время анимации. Нужно для частичного воспроизведения анимации |
void setEndTime(float)
|
Устанавливает конечное время анимации. Нужно для частичного воспроизведения анимации |
StateHandlerId setStateHandler(State state, StateHandler handler)
void resetStateHandler(StateHandlerId handler)
|
Устанавливает и удаляет callback на смену состояния на заданное. Сигнатура callback - void(Animator&) |
void setTimeHandler(float dt, TimeHandler handler)
|
Устанавливает callback на прохождение заданной временной метки. Сигнатура callback - void(Animator&) |
float getFps() const
|
Возвращает характеристику анимации - количество значений в секунду. |
float getDuration() const
|
Возвращает длительность анимации |
ParticlesEmitter
Особенности:
- ParticlesEmitter может быть загружен только из файла;
- Входным форматом файла является CoronaSDK (можно создать в любом онлайн-редакторе, например в http://www.effecthub.com/particle2dx, сохранить json с расширением part и текстуру и убедиться, что путь к текстуре является путём от корня проекта).
Важно понимать и учитывать, что в связи с ограниченными вычислительными и асинхронными возможностями технологии WebAssembly на текущий момент, система частиц отображается на плоскости, развёрнутой к камере.
API ParticlesEmitter:
Method | Description |
---|---|
void start()
|
Запуск генерации частиц |
void pause()
|
Приостановка генерации частиц. В этом случае обработка уже выпущенных частиц продолжается |
void resume()
|
Возобновление генерации частиц |
void stop()
|
Остановка генерации частиц. Обработка всех частиц прекращается |
State getState() const
|
Получение состояния
Варианты: ParticlesEmitter::State::IDLE, ParticlesEmitter::State::STARTED, ParticlesEmitter::State::PAUSED |
Billboard
Плоскость заданного при создании размера, всегда ориентированная на камеру. Имеет методы getSize и setSize.
Plotter
Реализация рисования линиями. Данные плоттера представляют собой информацию о точках (позиция и цвет) и набор индексов для их попарного соединения.
Пример:
auto plotter1 = make::sptr<Plotter>("Plotter_1");
const std::vector<uint32_t> indices = {1, 0};
const std::vector<LinesVertexFormat> vertices = {{{-10, -10, 0}, {1, 0, 0,1}},
{{10, 10, 0}, {0, 1, 0, 1}}};
plotter1->setLines(vertices, indices);
Представленный выше пример создаст косую линию с цветом, переходящим из красного в зелёный.
Как правило, для создания примитивов используются статические хелперы, возвращающие готовый объект, описанные в классе Plotter:
static w4::sptr<Plotter> build(std::vector<LinesVertexFormat> vertices, std::vector<uint32_t> indices);
static w4::sptr<Plotter> buildFromSegments(std::vector<std::array<w4::math::vec3, 2>> segments, const w4::math::vec4& color);
static w4::sptr<Plotter> buildFromPolyline(std::vector<w4::math::vec3> points, const w4::math::vec4& color);
static w4::sptr<Plotter> buildSphere(float radius, size_t rings, size_t sectors, const w4::math::vec4& color);
static w4::sptr<Plotter> buildOctahedron(std::array<w4::math::vec3, 8> vertices, const w4::math::vec4& color);
static w4::sptr<Plotter> buildCube(std::array<w4::math::vec3, 2> inVertices, const w4::math::vec4& color);
static w4::sptr<Plotter> buildCapsule(float radius, float height, size_t rings, size_t sectors, const w4::math::vec4& color);
static w4::sptr<Plotter> buildMesh(w4::cref<Mesh>, w4::math::vec4::cref color);
static w4::sptr<Plotter> buildMesh(w4::cref<SkinnedMesh>, w4::math::vec4::cref color);
static w4::sptr<Plotter> buildRay(math::vec3::cref startPoint, math::vec3::cref directionPoint, const w4::math::vec4& color);
DataNode
В отличие от VisibleNode, DataNode не отображается на экране. Далее описывается API унаследованных классов.
ArcBallNode
Аркболл для нижележащих объектов иерархии. Реализует контейнер, позволяющий вращать содержимое, как если бы оно находилось в шаре с инерцией.
Method | Description |
---|---|
ArcBallNode(const std::string& name = core::Object::defaultName, float radius = 1.f)
|
Конструктор, принимающий имя и радиус "шара" |
void setFriction(float v)
|
Задать коэффициент затухания скорости. По умолчанию = 0.95 |
void setSensitivity(float v)
|
Задать множитель чувствительности к прикосновению. По умолчанию = 1 |
void setRadius(float r)
|
Задать радиус |
void setVelocity(const math::Rotator& v)
|
Задать угловую скорость |
void enableUpdate(bool flag = true)
void disableUpdate()
|
Включить/отключить вращение аркболла. Не сбрасывает скорость, при включении - может продолжить вращаться (затухание скорости по времени) |
void enableInput(bool flag = true)
void disableInput()
|
Включение/выключение перехвата прикосновений аркболлом |
Camera
Method | Description |
---|---|
Camera(const std::string& name)
Camera(const std::string& name, float fov, float aspect, float near, float far)
|
Конструкторы перспективной камеры. Можно сразу указать FOV(угол обзора камеры по горизонтали), соотношение сторон и clip плоскости. FOV указывается в градусах |
Camera(const std::string& name, const math::size& screen, float near, float far)
|
Конструктор ортокамеры. Указываются размеры и clip плоскости камеры |
float getFov() const
void setFov(float v)
|
Получить, установить FOV(угол обзора камеры по горизонтали). FOV указывается в градусах |
float getAspect() const
void setAspect(float v)
|
Получить/установить соотношение сторон |
float getNear() const
void setNear(float v)
|
Получить/установить near clip плоскость |
float getFar() const
void setFar(float v)
|
Получить/установить far clip плоскость |
bool getIsOrtho() const
|
Получить является ли камера ортокамерой |
void setClearColor(const math::vec4& v)
|
Задать значение цвета для очистки буфера цвета (фоновый цвет для камеры при отсутствии Background или Skybox) |
ClearMask getClearMask() const
void setClearMask(ClearMask v)
|
Получить/установить ,битовую маску режима очистки экрана. Это значение будет применяться при рендеринге каждого кадра.
Значение по умолчанию ClearMask::Color | ClearMask::Depth Возможные значения: None Color - очищать буфер цвета Depth - очищать буфер глубины Skybox - отрисовывать ли skybox Background - отрисовывать ли background |
bool hasSkybox() const
w4::cref<Skybox> getSkybox() const
|
Получить текущий объект skybox или nullptr при его отсутствии |
bool hasBackground() const
w4::cref<Background> getBackground() const
|
Получить текущий объект background или nullptr при его отсутствии |
Background
Background представляет собой ресурсовыгодный способ очистки буфера цвета чем-то, что сложнее одного цвета.
Может использоваться двумя способами:
- Вызовом метода void setTexture(w4::cref<resources::Texture> texture). При вызове создастся материал по умолчанию (просто отображает текстуру).
- Работа с материалами вручную через методы void setMaterial(w4::cref<resources::MaterialInst>) и w4::sptr<resources::MaterialInst> getMaterial(). Вертексный шейдер должен использовать нормализованное пространство координат (т.е. [-1; 1])
Skybox
В случае если необходимо чтобы фон смещался при движении камеры, можно использовать объект Skybox. Он также может использоваться двумя способами:
1. Вызовом метода void setCubemap(w4::cref<resources::Cubemap> texture). При вызове создастся материал по умолчанию (просто отображает текстуру).
Пример:
auto cubemap = Cubemap::get({"resources/textures/left.png",
"resources/textures/right.png",
"resources/textures/up.png",
"resources/textures/down.png",
"resources/textures/front.png",
"resources/textures/back.png",
});
m_cam->setClearMask(ClearMask::Color | ClearMask::Depth | ClearMask::Skybox);
m_cam->getSkybox()->setCubemap(cubemap);
2. Работа с материалами вручную через методы void setMaterial(w4::cref<resources::MaterialInst>) и w4::sptr<resources::MaterialInst> getMaterial(). Вертексный шейдер должен использовать нормализованное пространство координат (т.е. [-1; 1])
PointLight
Точечный источник освещения. Имеет следующий API:
Method | Description |
---|---|
math::vec3 getColor() const
void setColor(const math::vec3& c)
|
Получить/установить цвет света |
float getIntensity() const
void setIntensity(float i)
|
Получить/установить яркость источника света |
core::LightDecayRate getDecayRate() const
void setDecayRate(core::LightDecayRate)
|
Получить/установить алгоритм затухания цвета (None, Linear, Quadratic, Cubic). |
SpotLight
Направленный источник освещения в виде конуса с вершиной в точке излучения.
Method | Description |
---|---|
float getAngle() const
void setAngle(float r)
|
Получить/установить верхний угол конуса |
math::vec3 getColor() const
void setColor(const math::vec3& c)
|
Получить/установить цвет света |
float getIntensity() const
void setIntensity(float i)
|
Получить/установить яркость источника света |
core::LightDecayRate getDecayRate() const
void setDecayRate(core::LightDecayRate)
|
Получить/установить алгоритм затухания цвета (None, Linear, Quadratic, Cubic) |
float getDecayFactor() const
void setDecayFactor(float f)
|
Получить/установить степень затухания(“прозрачность“) цвета от 0 до 1(по умолчанию = 1) |
Spline
Позволяет использовать траектории, импортированные из fbx (b-spline).
Важно понимать, что в формате FBX Spline содержит только саму траекторию, но не вращения вокруг неё (spin).
Method | Description |
---|---|
bool isRepeatable() const
void setRepeatable(bool isRepeatable)
|
Получить/установить режим повторяющегося “воспроизведения” |
void play(float splineTime, std::function<void(const math::Transform&)> updateHandler, std::function<void(bool)> completionHandler = [](bool){})
|
Запуск “воспроизведения” сплайна
splineTime - конечное время воспроизведения сплайна(для расчёта множителя скорости) updateHandler - метод, в который будут приходить Transform completionHandler - метод, который вызовется при завершении “воспроизведения” (если не задано повторение) |
void stop()
|
Остановить “воспроизведение” преобразований |
bool isPlaying() const
|
Возвращает, идёт ли “воспроизведение” сплайна |
bool isPaused() const
void pause()
|
Приостановка “воспроизведения” сплайна |
float getDuration() const
|
Возвращает длительность сплайна в секундах |
void setPosition(float pos)
|
Устанавливает позицию в секундах |