1#include "Foundation/Logging/Logger.h"
3#include "TransformSystem.h"
7#include <glm/mat4x4.hpp>
8#include <glm/ext/quaternion_float.hpp>
9#include <glm/gtx/matrix_decompose.hpp>
11#include "Services/Variables.h"
13#include "Utilities/Parallel.h"
22 const auto & transformState = system->getData<
TransformState>(component);
24 bool componentChanged = !transformState.cached || component->hasChanged();
26 if(
auto * parentTransform = component->parent.resolveComponent<
TransformComponent>(); parentTransform) {
27 return componentChanged || transformChainChanged(system, parentTransform);
29 return componentChanged;
40 TransformState & transformState = this->getData<TransformState>(&component);
42 transformState.cached = !transformChainChanged(
this, &component);
43 transformState.changed = !transformState.cached;
50 updateLocalTransform(component);
56 for (
auto & component :
pool) {
57 TransformState & transformState = this->getData<TransformState>(&component);
59 transformState.cached = !transformChainChanged(
this, &component);
60 transformState.changed = !transformState.cached;
63 for (
auto & component :
pool) {
64 if (component.hasChanged()) {
65 updateLocalTransform(component);
71 CpuInstrumentationScope(SCOPE_SYSTEMS,
"TransformSystem::updateLocalToWorldTransform");
72 for (
auto & component :
pool) {
73 updateLocalToWorldTransform(component);
78void Cogs::Core::TransformSystem::handleOriginUpdate(
class Context* )
80 if (origin.x == originUpdate.x && origin.y == originUpdate.y && origin.z == originUpdate.z) {
86 origin = originUpdate;
87 for (
auto& component : pool) {
88 component.setChanged();
92void Cogs::Core::TransformSystem::setLocalTransform(
TransformComponent* component,
const glm::mat4& matrix)
104 float uniformScale = std::cbrt(std::abs(glm::determinant(glm::mat3(matrix))));
105 float reciprocalUniformScale = 1.f / uniformScale;
106 if (std::isfinite(reciprocalUniformScale)) {
107 glm::mat4 conditionedMatrix = matrix * glm::mat4(reciprocalUniformScale, 0.f, 0.f, 0.f,
108 0.f, reciprocalUniformScale, 0.f, 0.f,
109 0.f, 0.f, reciprocalUniformScale, 0.f,
113 glm::vec4 perspective;
114 if (glm::decompose(conditionedMatrix, component->
scale, component->
rotation, component->
position, skew, perspective)) {
118 if (std::numeric_limits<float>::epsilon() <= dot(skew, skew)) {
119 LOG_WARNING(logger,
"Transform matrix contains skew, which is not supported, using matrix directly. Check your models.");
123 else if (
auto t = perspective - glm::vec4(0, 0, 0, 1); std::numeric_limits<float>::epsilon() <= dot(t, t)) {
124 LOG_WARNING(logger,
"Transform matrix contains perspective, which is not supported, using matrix directly. Check your models.");
131 component->
scale *= uniformScale;
136 LOG_WARNING(logger,
"Failed to decompose matrix, using matrix directly and position/scale/rotation will have no effect. Check your models.");
142 LOG_ERROR(logger,
"Transform matrix probably totally broken, ignoring. Check your models.");
143 component->
position = glm::vec3(0.f);
145 component->
scale = glm::vec3(1.f);
148 getLocalTransform(component) = matrix;
153 getData<TransformState>(component).cached =
false;
156void Cogs::Core::TransformSystem::updateLocalToWorldTransform(
const TransformComponent & component,
bool dirty)
158 auto & transformState = getData<Core::TransformState>(&component);
160 if (transformState.cached && !dirty)
return;
162 if (dirty) updateLocalTransform(component);
167 updateLocalToWorldTransform(*parent, dirty);
169 getLocalToWorld(&component) = getLocalToWorld(parent) * getLocalTransform(&component);
171 getLocalToWorld(&component) = getLocalTransform(&component);
174 transformState.changed =
true;
175 transformState.cached =
true;
void resetCarryChanged()
Reset the CarryChanged flag. Called at start of redraw. See ComponentFlags::CarryChanged.
void resetChanged()
Resets the changed state of the component, respecting any carry state set.
Context * context
Pointer to the Context instance the system lives in.
void update()
Updates the system state to that of the current frame.
ComponentPool< ComponentType > pool
Pool of components managed by the system.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
std::unique_ptr< class Engine > engine
Engine instance.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
constexpr Log getLogger(const char(&name)[LEN]) noexcept
ComponentType * resolveComponent() const