[scene] Track hierarchies instead of root transforms

The root transform of each hierarchy can be extracted from the first
transform of the list in the hierarchy, so no information is lost. The
main reason for the change is I discovered (obvious in hindsight) that
deleting root transforms was O(n) due to keeping them in an array, thus
the use of a linked list (I don't expect a hierarchy to be in more than
one such list), and I didn't want the transforms to be in a linked list.
This commit is contained in:
Bill Currie 2022-03-04 06:43:30 +09:00
parent 7906db5a37
commit 6ec8e29429
6 changed files with 18 additions and 36 deletions

View file

@ -45,6 +45,9 @@
#define null_transform (~0u)
typedef struct hierarchy_s {
struct hierarchy_s *next;
struct hierarchy_s **prev;
struct scene_s *scene;
xformset_t transform;
entityset_t entity;
uint32set_t childCount;
@ -61,7 +64,6 @@ typedef struct hierarchy_s {
vec4fset_t localScale;
vec4fset_t worldRotation;
vec4fset_t worldScale;
struct scene_s *scene;
} hierarchy_t;
hierarchy_t *Hierarchy_New (struct scene_s *scene, int createRoot);

View file

@ -42,7 +42,7 @@
typedef struct scene_s {
struct scene_resources_s *const resources;
xformset_t roots;
struct hierarchy_s *hierarchies;
} scene_t;
scene_t *Scene_NewScene (void);

View file

@ -13,7 +13,4 @@ typedef struct scene_resources_s {
PR_RESMAP (transform_t) transforms;
} scene_resources_t;
void scene_add_root (scene_t *scene, transform_t *transform);
void scene_del_root (scene_t *scene, transform_t *transform);
#endif//__scn_internal_h

View file

@ -403,6 +403,13 @@ Hierarchy_New (scene_t *scene, int createRoot)
hierarchy_t *hierarchy = PR_RESNEW_NC (res->hierarchies);
hierarchy->scene = scene;
hierarchy->prev = &scene->hierarchies;
hierarchy->next = scene->hierarchies;
if (scene->hierarchies) {
scene->hierarchies->prev = &hierarchy->next;
}
scene->hierarchies = hierarchy;
size_t grow = 16;
DARRAY_INIT (&hierarchy->transform, grow);
DARRAY_INIT (&hierarchy->entity, grow);
@ -432,6 +439,11 @@ Hierarchy_New (scene_t *scene, int createRoot)
void
Hierarchy_Delete (hierarchy_t *hierarchy)
{
if (hierarchy->next) {
hierarchy->next->prev = hierarchy->prev;
}
*hierarchy->prev = hierarchy->next;
scene_resources_t *res = hierarchy->scene->resources;
for (size_t i = 0; i < hierarchy->transform.size; i++) {
PR_RESFREE (res->transforms, hierarchy->transform.a[i]);

View file

@ -54,8 +54,6 @@ Scene_NewScene (void)
res = calloc (1, sizeof (scene_resources_t));
*(scene_resources_t **)&scene->resources = res;
DARRAY_INIT (&scene->roots, 16);
return scene;
}
@ -70,8 +68,6 @@ Scene_DeleteScene (scene_t *scene)
}
free (res->entities._map);
DARRAY_CLEAR (&scene->roots);
free (scene->resources);
free (scene);
}
@ -98,27 +94,6 @@ Scene_GetEntity (scene_t *scene, int id)
return PR_RESGET (res->entities, id);
}
void
scene_add_root (scene_t *scene, transform_t *transform)
{
if (!Transform_GetParent (transform)) {
DARRAY_APPEND (&scene->roots, transform);
}
}
void
scene_del_root (scene_t *scene, transform_t *transform)
{
if (!Transform_GetParent (transform)) {
for (size_t i = 0; i < scene->roots.size; i++) {
if (scene->roots.a[i] == transform) {
DARRAY_REMOVE_AT (&scene->roots, i);
break;
}
}
}
}
static void
destroy_entity (scene_t *scene, entity_t *ent)
{
@ -154,8 +129,8 @@ Scene_DestroyEntity (scene_t *scene, entity_t *ent)
void
Scene_FreeAllEntities (scene_t *scene)
{
for (size_t i = 0; i < scene->roots.size; i++) {
hierarchy_t *h = scene->roots.a[i]->hierarchy;
while (scene->hierarchies) {
hierarchy_t *h = scene->hierarchies;
// deleting the root entity deletes all child entities
entity_t *ent = h->entity.a[0];
destroy_entity (scene, ent);

View file

@ -58,7 +58,6 @@ Transform_New (scene_t *scene, transform_t *parent)
} else {
transform->hierarchy = Hierarchy_New (scene, 1);
transform->index = 0;
scene_add_root (scene, transform);
}
transform->hierarchy->transform.a[transform->index] = transform;
Hierarchy_UpdateMatrices (transform->hierarchy);
@ -73,7 +72,6 @@ Transform_Delete (transform_t *transform)
// hierarchy so deleting it is easier
Transform_SetParent (transform, 0);
}
scene_del_root (transform->scene, transform);
// Takes care of freeing the transforms
Hierarchy_Delete (transform->hierarchy);
}
@ -90,7 +88,6 @@ void
Transform_SetParent (transform_t *transform, transform_t *parent)
{
if (parent) {
scene_del_root (transform->scene, transform);
hierarchy_t *hierarchy = transform->hierarchy;
uint32_t index = transform->index;
Hierarchy_InsertHierarchy (parent->hierarchy, hierarchy,
@ -112,7 +109,6 @@ Transform_SetParent (transform_t *transform, transform_t *parent)
Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform,
index);
Hierarchy_RemoveHierarchy (hierarchy, index);
scene_add_root (transform->scene, transform);
}
}