fix: transform updating is now _actually_ recursive through the whole tree
This commit is contained in:
parent
c7265739cc
commit
09e52d007a
|
@ -5,6 +5,29 @@
|
|||
#include "utils/drop.h"
|
||||
#include "utils/mirror.h"
|
||||
|
||||
//! Tick a node and all children recursively
|
||||
static
|
||||
void Internal_SceneNodeTick(SceneNode *self, double delta) {
|
||||
// tick self first
|
||||
self->entity.tc->tick(self->entity.data, delta);
|
||||
// fix the number of elements to update now,
|
||||
// so that if/when new children are added, they don't get ticked until next frame
|
||||
size_t const len = self->children.len;
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
Internal_SceneNodeTick(*list_at_as(SceneNode*, &self->children, i), delta);
|
||||
}
|
||||
|
||||
//! Update global transform of a node
|
||||
static
|
||||
void Internal_SceneNodeUpdateTransform(SceneNode *self) {
|
||||
if(TC_MIRRORS(self->entity, Transformable)) {
|
||||
Transformable transformable = TC_CAST(self->entity, Transformable);
|
||||
if(transformable.tc->get_dirty_bit(transformable.data)) {
|
||||
transformable.tc->force_update(transformable.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Remove a single node (does NOT recurse to children children) from this scene.
|
||||
static
|
||||
void Internal_SceneRemoveNode(Scene *self, SceneNode *node) {
|
||||
|
@ -44,34 +67,18 @@ void Internal_SceneAddNode(Scene *self, SceneNode *node) {
|
|||
list_add(&self->nodes, &node);
|
||||
// establish two-way relationship
|
||||
Internal_SceneNodeSetScene(node, self);
|
||||
Internal_SceneNodeUpdateTransform(node);
|
||||
// do the same for all children (and their children) recursively
|
||||
list_foreach(SceneNode **,child, &node->children)
|
||||
Internal_SceneAddNode(self, *child);
|
||||
}
|
||||
|
||||
//! Tick a node and all children recursively
|
||||
static
|
||||
void Internal_SceneNodeTick(SceneNode *self, double delta) {
|
||||
// tick self first
|
||||
self->entity.tc->tick(self->entity.data, delta);
|
||||
// fix the number of elements to update now,
|
||||
// so that if/when new children are added, they don't get ticked until next frame
|
||||
size_t const len = self->children.len;
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
Internal_SceneNodeTick(*list_at_as(SceneNode*, &self->children, i), delta);
|
||||
}
|
||||
|
||||
//! Update global transforms of all children recursively
|
||||
static
|
||||
void Internal_SceneNodeUpdateTransform(SceneNode *self) {
|
||||
if(TC_MIRRORS(self->entity, Transformable)) {
|
||||
Transformable transformable = TC_CAST(self->entity, Transformable);
|
||||
if(transformable.tc->get_dirty_bit(transformable.data)) {
|
||||
transformable.tc->force_update(transformable.data);
|
||||
}
|
||||
}
|
||||
void Internal_SceneNodeUpdateTransformRecursive(SceneNode *self) {
|
||||
Internal_SceneNodeUpdateTransform(self);
|
||||
list_foreach(SceneNode **,child, &self->children)
|
||||
Internal_SceneNodeUpdateTransform(*child);
|
||||
Internal_SceneNodeUpdateTransformRecursive(*child);
|
||||
}
|
||||
|
||||
SceneNode *CreateSceneNode(SceneNodeEntity entity) {
|
||||
|
@ -159,12 +166,12 @@ Scene *CreateScene(SceneNode *root) {
|
|||
}
|
||||
|
||||
void DestroyScene(Scene *self) {
|
||||
DestroySceneNode(self->root);
|
||||
DestroySceneNode(self->root); // recurses to the rest of the scene
|
||||
list_empty(&self->nodes);
|
||||
free(self);
|
||||
}
|
||||
|
||||
void SceneTick(Scene* self, double delta_time) {
|
||||
Internal_SceneNodeTick(self->root, delta_time);
|
||||
Internal_SceneNodeUpdateTransform(self->root);
|
||||
Internal_SceneNodeUpdateTransformRecursive(self->root);
|
||||
}
|
||||
|
|
|
@ -58,16 +58,15 @@ extern Transform InverseTransformTransform(Transform const *self, Transform cons
|
|||
//! Macro implements the interface functions itself to ensure consistent behaviour.
|
||||
#define impl_Transformable_for(T)\
|
||||
static Transform T##_get_transform_GEN_(T* self) { return self->transform; }\
|
||||
static void T##_set_transform_GEN_(T* self, Transform value) { self->transform = value; self->dirty_bit |= 0x1; } /*!< sets local dirty bit */\
|
||||
static void T##_set_transform_GEN_(T* self, Transform value) { self->transform = value; self->dirty_bit |= 1u; } /*!< sets dirty bit */\
|
||||
static Transform T##_get_global_transform_GEN_(T* self) { return self->global_transform; }\
|
||||
static void T##_set_global_transform_GEN_(T* self, Transform value) {\
|
||||
self->global_transform = value;\
|
||||
if(tc_is_null(self->parent_transformable)) {\
|
||||
self->transform = value;\
|
||||
} else {\
|
||||
self->parent_transformable.tc->force_update(self->parent_transformable.data); /* Force a transform update for the parent, to ensure its global transform is up-to-date */\
|
||||
Transform parent_global = self->parent_transformable.tc->get_global_transform(self->parent_transformable.data);\
|
||||
self->transform = InverseTransformTransform(&parent_global, &value); /* Use up-to-date parent transform to get the local transform to the new global transform */\
|
||||
self->transform = InverseTransformTransform(&parent_global, &value); /* Use parent transform to transform the local transform to the new global transform */\
|
||||
}\
|
||||
}\
|
||||
static void T##_force_update_GEN_(T *self) {\
|
||||
|
|
Loading…
Reference in a new issue