Difference between revisions of "W4 Coordinate system and Node structure"
Line 16: | Line 16: | ||
* The built-in node types hierarchy is displayed on the diagram below. | * The built-in node types hierarchy is displayed on the diagram below. | ||
− | [[File: | + | [[File:Concept02G.png|Type hierarchy|500 px]] |
The purpose and interfaces of nodes (classes) are presented in the following paragraphs. | The purpose and interfaces of nodes (classes) are presented in the following paragraphs. |
Latest revision as of 14:02, 19 August 2020
W4 Engine Wiki > General Concepts > Coordinate system and Node structure:
Contents
Scope
The article describes the main solutions used in the W4 game engine:
- Coordinate system
- Node system
- Node system main classes API
Coordinate System
The W4 Engine uses the left-handed coordinate system. The rotation is performed counterclockwise provided you look in the direction of the axis.
Render Tree
The result displayed on the screen as well as the dependence of object transformations on each other, are determined by the render tree (tree-like structure of node objects). Features of the W4 Game Engine render tree:
- A minimal render tree consist of the root node only.
- Each node can have zero or more subnodes (“children”), but the node cannot have more than one “parent” (the root node does not have a parent).
- The object has to be placed on the render tree in order to be displayed on the screen and/or recalculate the data.
- The built-in node types hierarchy is displayed on the diagram below.
The purpose and interfaces of nodes (classes) are presented in the following paragraphs.
Usage notes:
- When drawing several passes, a render tree with its root node is created for each pass.
- For each node, the local transformations (transformations relative to the “parent") and the world transformations can be obtained and specified.
- When world coordinates of a node are set, local coordinates are recalculated, and same correlation between local and world coordinates.
- For a node that does not have a parent, local and world transformations match.
- You can temporarily disable the node, thus disabling its descendants as well.
Node
Node is the base class of any node (including RootNode).
Method | Description |
---|---|
w4::sptr<render::RootNode> getRoot() const
|
Returns root node of render tree or "nullptr" if there is none |
w4::sptr<Node> clone() const
|
Creates a copy of the node. The created copy does not have a parent node |
w4::sptr<Node> getParent() const
|
Returns the parent node or "nullptr" if there is none |
void setEnabled(bool)
|
Enables/disables the node and his "descendants" |
void addChild(w4::cref<Node>, bool preserveTransorm = true)
void addChild(const std::string&, w4::cref<Node>, bool preserveTransorm = true)
|
Adds “children” to the current node. In this method you can set a name for the "child". The "preserveTransform" parameter defines local (false) or global (true) transformations that are stored in the “child".
For example, if you complete the code on the left with the lines: childNode->setLocalTranslation({1, 0, 0});
parentNode->addChild(childNode);
then "childNode" is in the world position {1, 0, 0}, On the other hand, if you use the following lines: childNode->setLocalTranslation({1, 0, 0});
parentNode->addChild(childNode, false);
then "childNode" is shifted by 1 on the X axis relative to the parent. |
void removeChild(w4::cref<Node>)
void removeChild(const std::string&)
void removeChild(const std::list<w4::sptr<Node>>&)
|
Unlinks “children” from node defined by pointer, name and list |
void traversal(const Callback&)
void traversal(const PredicateC & predicate, const Callback&)
template<typename T> void traversalTyped(const std::function<void(w4::cref<T>)>&);
|
Executing the functor from the current node down the hierarchy
Callback has a signature void(Node&) PredicateC - bool(w4::core::Node&) The last method calls functor only for those nodes whose type is inherited from T |
void setWorldRotation(math::Rotator::cref, math::vec3::cref worldPt)
|
Sets rotation relative to a point in world coordinates |
void rotateAroundPoint(const math::Rotator& rotator, const math::vec3& worldPt)
|
Rotates node around a point in world coordinates |
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
|
Conversion of type of the node (the type is not checked) |
template<typename T> bool derived_from() const
|
Checks if node class is a descendant of the defined class |
template<typename T> w4::sptr<T> getChild(const std::string&)
|
Gets “child” by name with type conversion (the specified type is not checked) |
std::list<w4::sptr<Node>> getAllChildren() const
|
Gets list of all lower nodes in the hierarchy (“children“, “children of children“, etc.) |
std::list<w4::sptr<Node>> findChildren(std::string const&) const
|
Searches for “child” by name |
std::list<w4::sptr<Node>> findChildrenRecursive(std::string const&) const
|
Searches down the hierarchy by name |
math::vec3::cref getWorldTranslation() const
void setWorldTranslation(math::vec3::cref)
math::vec3::cref getLocalTranslation() const
void setLocalTranslation(math::vec3::cref)
|
Gets/sets position in world/local coordinates |
math::vec3::cref getWorldScale() const
void setWorldScale(math::vec3::cref)
math::vec3::cref getLocalScale() const
void setLocalScale(math::vec3::cref)
|
Gets/sets scale in world/local coordinates |
math::vec3 getWorldUp() const
math::vec3 getWorldForward() const
math::vec3 getWorldRight() const
|
Gets normalized vectors in the up, forward, and right directions of the model space in world coordinates |
math::Transform::cref getWorldTransform() const
void setWorldTransform(math::Transform::cref)
math::Transform::cref getLocalTransform() const
void setLocalTransform(math::Transform::cref)
|
Gets/sets transformation (i.e. combination of position, rotation and scale) in world/local coordinates |
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)
|
Gets/sets rotation in world/local coordinates. "rotateWorld" and "rotateLocal" methods add rotation to the current values |
const std::unordered_set<w4::sptr<Node>>& getChildren() const
|
Gets list of “children“ |
bool isEnabled() const
|
Returns the node state (enabled or disabled) |
bool hasParent() const
|
Returns if the node has a “parent” |
Hierarchy Example
Let's take real astronomical dimensions and build a simplified model of the solar system. Since real space distances are used, it is not possible to survey the entire system. In this particular case the model was selected not for visualization purpose, but as a pattern of the features of hierarchy and nesting of transforms (although nothing prevents you from trying to make the model more visual).
#include "W4Framework.h"
W4_USE_UNSTRICT_INTERFACE
class Planet
{
public:
//Some astronomical object data:
// - name
// - color
// - radius (km)
// - radius of the orbit (km)
// - orbital period (days)
// - orbital inclination
// - axis tilt
// - list of satellites
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
{
//create the solar system at the start
createSolarSystem();
}
void onMove(const event::Touch::Move& evt)
{
}
void onUpdate(float dt) override
{
for(auto& rotation: m_rotations)
{
//object rotation around central body at speed of 0.5 days per second
rotation.first->rotateLocal(rotation.second * (dt / 2));
}
}
private:
void createSolarSystem()
{
// here it is - the solar system!
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, {}}
}}
});
//Create the Sun
auto sun = Mesh::create::sphere(solarSystem.m_radius, 10, 10);
//Add it to the root node
Render::getRoot()->addChild(sun);
//Set color of base material
sun->getMaterialInst()->setParam("baseColor", solarSystem.m_color);
//Create planets
createMoons(sun, solarSystem);
//Set scale. Alas, distances are extremely remote that is only the Sun that is visible with real distances without a magnifier... But this is an example
sun->setLocalScale({1.e-7f, 1.e-7f, 1.e-7f});
}
void createMoons(cref<Node> planetNode, const Planet& planet)
{
//for each satellite
for(const auto& moon: planet.m_moons)
{
//To test the possibilities of nesting, create an orbit as a node. When this node rotates around the center, the satellite moves in orbit
auto orbitContainer = make::sptr<Node>();
//tilt the orbit from the plane of rotation of the central body
orbitContainer->setLocalRotation({(planet.m_axisTilt + moon.m_eclipseAngle) * DEG2RAD, 0, 0});
//create an astronomical object
auto moonNode = Mesh::create::sphere(moon.m_radius, 10, 10);
//add satellite as a "child" of the orbit
orbitContainer->addChild(moonNode);
//set position of the astronomical object in the orbit
moonNode->setLocalTranslation({moon.m_orbit, 0, 0});
moonNode->getMaterialInst()->setParam("baseColor", moon.m_color);
//add the orbit as a "child" of the central body. Pay attention to the "false" parameter which means that
//when a "child" is created, local transforms are saved. Thus, the orbit appears to be in the same
//position as the planet and is tilted relative to its plane of orbit around the central body
planetNode->addChild(orbitContainer, false);
//create satellites recursively
createMoons(moonNode, moon);
//add to the list orbits and quaternions for their rotation in local space (calculate from the Euler angles)
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
The base class for a visible node.
Special features:
- All displayed nodes contain a vertex buffer and consist of one or more surface (which contains an index buffer).
- Each surface can be assigned its own material.
All displayed nodes have the following additional methods:
Method | Description |
---|---|
const MaterialInstPtr& getMaterialInst(const std::string& surfaceName) const
|
Returns material of the specified surface |
const MaterialInstPtr& getMaterialInst() const
|
Gets single material (which was set for all surfaces). If materials differ for surfaces, the method generates an error in the log and returns some material back. |
void setMaterialInst(const MaterialInstPtr & m)
|
Sets material for all surfaces |
Mesh
An object that displays geometry.
There are three ways to create mesh type objects in the Engine: 1. Load from resources (see also Mesh Converter):
teapot = Asset::load(Path("resources/teapot", "teapot.asset"))->getRoot()->getChild<Mesh>("Utah Teapot Quads");
2. Call the built-in generator:
auto sphere = Mesh::create::sphere(radius, number of parallels, number of meridians);
auto box = Mesh::create::box({width, height, depth}); //"box" is a parallelepiped in which each face is a surface
auto cube = Mesh::create::cube({width, height, depth});
auto mappedCube = Mesh::create::mappedCube({width, height, depth}); //parallelepiped with uv coordinates for unfolding
auto plane1 = Mesh::create::plane({width, height}, scaleUv); //XY axis plane. scaleUv = false (default) is UV from 0 to 1, scaleUv = true is UV from 0 to width/height
auto plane2 = Mesh::create::plane({left, down}, {right, up}, scaleUv; //same
auto cylinder = Mesh::create::cylinder(height, radius, number of sectors);
auto cone = Mesh::create::cone(upper radius, lower radius, height, number of sectors, number of segments vertically);
auto torus = Mesh::create::torus(radius of the ring, radius of the "pipe", number of segments of the ring, number of segments of the "pipe", angle of the arc of the ring (2 * PI for a closed torus));
auto skybox = Mesh::create::skybox(); //Cuboid with sides that are displayed from the inside.
3. Create from code:
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);
//position, UV, normal
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
An object that displays geometry with animation.
Special features:
- it can only be downloaded from a file;
- it is a geometry with skeletal animation;
- it contains a set of animations;
- it contains an API for managing animations and allows you to play multiple animations with smooth transitions between them.
Method | Description |
---|---|
w4::cref<core::Node> createSocket(const std::string& boneName)
|
Creates a socket for attaching to the defined bone. You can add “children“ to this socket |
w4::cref<core::Node> getSocket(const std::string& boneName) const
|
Returns a socket for attaching to the defined bone |
std::vector<std::string> getAvailableAnimations() const
|
Returns a list of available animations |
bool haveAnimation(const std::string& animationName) const
|
Checks for animations with the defined name |
size_t getAnimationIndex(const std::string& animationName) const
|
Gets an animation index by name |
const std::string& getAnimationName(size_t animationIndex) const
|
Gets name of animation by index |
void setAnimationStateChangedCallback(std::function<void(Animator&, Animator::State)>)
void setAnimationStateChangedCallback(Animator::State, std::function<void(Animator&)>)
|
Sets a functor that will be called upon changing the state of a specific animation. The method has an options:
Animation states: Animator::State::Idle(Animation is not playing (including it is finished)), Animator::State::Play(Animation is still playing), Animator::State::Pause(Animation is paused) Example: 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)
|
Plays an animation by its index or name. Sets duration of animation, if it is equal to zero, then the entire animation is played |
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)
|
Plays a list of animations with weights. If duration is equal to zero, the method sets it equal to the animation with the maximum duration
Example: skinned->play({{"run", .3f}, {"jump", .7f}});
|
void pause()
|
Pauses all active animations |
void resume()
|
Resumes all paused animations |
void stop()
|
Stops playing all active animations |
bool isPlaying() const
|
Checks if any animation is playing now |
Animator & getAnimator(size_t)
Animator & getAnimator(const std::string&)
const Animator & getAnimator(size_t) const
const Animator & getAnimator(const std::string&) const
|
Gets animator object by name or index. The Animator API, which is used to control animations with advanced features, is described below.
Managing animations through the Animator API and SkinnedMesh are not mutually exclusive. For example, the following practice of looping animations is common: m_skinned->getAnimator("dance").setIsLooped(true);
|
Animator API
Method | Description |
---|---|
void play()
|
Starts playing animation
If it is already playing, it will be stopped and started from the beginning |
void pause()
|
Pauses animation playback |
void resume()
|
Resumes animation playback |
void stop()
|
Stops animation playback |
void seek(float targetTime)
|
Sets current position in the animation for defined time. Values are automatically trimmed from top and bottom to the range [0; animation duration] or to the range specified by setBeginTime/setEndTime |
bool isLooped() const
|
Returns if the loop playback state is enabled or disabled for this animation |
float getSpeed() const
|
Gets animation playback speed multiplier (default 1.0) |
State getState() const
|
Returns animation state
Possible animation states: Animator::State::Idle (animation is not playing or it is finished), Animator::State::Play (animation is still playing), Animator::State::Pause (animation is paused) |
void setPlayType(PlayType)
|
Sets playback direction
Possible parameter values: Animator::PlayType::Forward, Animator::PlayType::Backward |
PlayType getPlayType() const
|
Returns current playing direction. For possible values see setPlayType |
float getCurrentTime() const
|
Returns the current position in the animation |
void setIsLooped(bool)
|
Enables/disables the loop mode for the animation |
void setSpeed(float)
|
Sets the animation playback speed multiplier |
void setBeginTime(float)
|
Sets the start time of the animation. It is useful for partial animation playback |
void setEndTime(float)
|
Sets the end time of the animation. It is useful for partial animation playback |
StateHandlerId setStateHandler(State state, StateHandler handler)
void resetStateHandler(StateHandlerId handler)
|
Sets/removes a callback to change the animation state to the specified one. Signature is callback - void (Animator &) |
void setTimeHandler(float dt, TimeHandler handler)
|
Sets the callback to pass the specified timestamp. Signature callback - void (Animator &) |
float getFps() const
|
Returns the number of values per second (animation characteristic) |
float getDuration() const
|
Returns the duration of the animation |
ParticlesEmitter
Special features:
- ParticlesEmitter can only be loaded from a file;
- The input file format is CoronaSDK (you can create it in any online editor, for example, at http://www.effecthub.com/particle2dx, save JSON with the extension part and texture and make sure that you use the path to the texture from the project root).
Bear in mind that due to the limited computational and asynchronous capabilities of WebAssembly technology currently, the particle system is displayed on a plane turned toward the camera.
API ParticlesEmitter:
Method | Description |
---|---|
void start()
|
Starts particle generation |
void pause()
|
Pauses particle generation. In this case, the processing of already released particles still continues |
void resume()
|
Resumes particle generation |
void stop()
|
Stops the processing of all particles |
State getState() const
|
Gets the state
Options: ParticlesEmitter::State::IDLE, ParticlesEmitter::State::STARTED, ParticlesEmitter::State::PAUSED |
Billboard
A plane of a set size, always oriented towards the camera. It has methods getSize and setSize.
Plotter
Implementation of line drawing. The plotter data is an information about the dots (position and color) and a set of indices for pairing them.
Example:
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);
The example above will create a diagonal line with a color changing from red to green.
To create primitives, you can use static helpers that return a completed object. They are described in the Plotter class:
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
Unlike VisibleNode, DataNode is not displayed on the screen.
The following paragraphs describe the API for inherited classes.
ArcBallNode
Arcball implements a container (for underlying hierarchy objects) that allows you to rotate the contents as if they were in an inertia ball.
Method | Description |
---|---|
ArcBallNode(const std::string& name = core::Object::defaultName, float radius = 1.f)
|
Constructor that receives the name and radius of the ball |
void setFriction(float v)
|
Sets speed damping coefficient. Default = 0.95 |
void setSensitivity(float v)
|
Sets touch sensitivity multiplier. Default = 1 |
void setRadius(float r)
|
Sets radius of Arcball |
void setVelocity(const math::Rotator& v)
|
Sets angular velocity |
void enableUpdate(bool flag = true)
void disableUpdate()
|
Enables/disables arcball rotation. It does not slow down the rotation of the arcball. When turned on, it can continue to rotate (time damping) |
void enableInput(bool flag = true)
void disableInput()
|
Enables/disables interception of touch events by arcball |
Camera
Method | Description |
---|---|
Camera(const std::string& name)
Camera(const std::string& name, float fov, float aspect, float near, float far)
|
Perspective camera constructors. You can specify the FOV, aspect ratio, and plane clip. FOV is set in degrees |
Camera(const std::string& name, const math::size& screen, float near, float far)
|
Orthocamera constructor. You can specify dimensions and near/far clip plane of the camera |
float getFov() const
void setFov(float v)
|
Gets/sets FOV. FOV is set in degrees |
float getAspect() const
void setAspect(float v)
|
Gets/sets aspect ratio |
float getNear() const
void setNear(float v)
|
Gets/sets near clip plane |
float getFar() const
void setFar(float v)
|
Gets/sets far clip plane |
bool getIsOrtho() const
|
Gets the camera type (orthocamera or not) |
void setClearColor(const math::vec4& v)
|
Sets the color value to clear the color buffer (background color for the camera in the absence of Background or Skybox) |
ClearMask getClearMask() const
void setClearMask(ClearMask v)
|
Gets/sets bit mask of screen cleaning mode. This value will be applied to render each frame
The default value: ClearMask::Color|ClearMask::Depth Possible values: None Color (clear color buffer) Depth (clear depth buffer) Skybox (render skybox or not) Background (render background or not) |
bool hasSkybox() const
w4::cref<Skybox> getSkybox() const
|
Gets current skybox object (or "nullptr" if none) |
bool hasBackground() const
w4::cref<Background> getBackground() const
|
Gets current background object (or "nullptr" if none) |
Background
Background is a resource-friendly way to clear a color buffer with something that is more complex than a single color.
It can be used in two ways:
- By calling the method void setTexture (w4::cref<resources::Texture>texture). When it called, the default material is created (it simply displays the texture).
- By working with materials manually through the methods 'void setMaterial (w4::cref<resources::MaterialInst>)' and w4::sptr<resources::MaterialInst> getMaterial (). The vertex shader should use normalized coordinate space ([-1; 1])
Skybox
If you want to shift the background when the camera moves, you can use the Skybox object. There are two ways to used it:
1. By calling the method void setCubemap (w4::cref<resources::Cubemap> texture). When called, the default material is created (it simply displays the texture).
Example:
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. By working with materials manually through the methods void setMaterial (w4::cref<resources::MaterialInst>) and w4::sptr<resources::MaterialInst> getMaterial (). The vertex shader should use normalized coordinate space ([-1; 1])
PointLight
A point source of light. It has the following API:
Method | Description |
---|---|
math::vec3 getColor() const
void setColor(const math::vec3& c)
|
Gets/sets color of the light |
float getIntensity() const
void setIntensity(float i)
|
Gets/sets brightness of the light source |
core::LightDecayRate getDecayRate() const
void setDecayRate(core::LightDecayRate)
|
Gets/sets color fading algorithm (None, Linear, Quadratic, Cubic). |
SpotLight
A directional light source in the form of a cone with a vertex at the point of the light source.
Method | Description |
---|---|
float getAngle() const
void setAngle(float r)
|
Gets/sets top corner of the cone |
math::vec3 getColor() const
void setColor(const math::vec3& c)
|
Gets/sets color of the light |
float getIntensity() const
void setIntensity(float i)
|
Gets/sets brightness of the light source |
core::LightDecayRate getDecayRate() const
void setDecayRate(core::LightDecayRate)
|
Gets/sets color fading algorithm (None, Linear, Quadratic, Cubic) |
float getDecayFactor() const
void setDecayFactor(float f)
|
Gets/sets degree of fading (“transparency") of the color from 0 to 1 (default = 1) |
Spline
Allows the use of trajectories imported from fbx (b-spline).
Note. In FBX format, Spline contains the only trajectory itself without a spin.
Method | Description |
---|---|
bool isRepeatable() const
void setRepeatable(bool isRepeatable)
|
Gets/sets repeated playback mode |
void play(float splineTime, std::function<void(const math::Transform&)> updateHandler, std::function<void(bool)> completionHandler = [](bool){})
|
Starts spline playback
splineTime: it is the final spline playing time which is used to calculate speed multiplier updateHandler: Transform data comes to this method completionHandler: This method is called when playback is completed (if no repetition is specified) |
void stop()
|
Stops playback of transformations |
bool isPlaying() const
|
Returns the spline state (playing or not) |
bool isPaused() const
void pause()
|
Pauses spline playback |
float getDuration() const
|
Returns the spline duration (in seconds) |
void setPosition(float pos)
|
Sets position (in seconds) |