From ba3879c6e03d5b4c2f61d1ff25393570e9bb7332 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 20:01:36 +0900 Subject: [PATCH] [scene] Make transforms owned by the scene This actually has at least two benefits: the transform id is managed by the scene and thus does not need separate management by the Ruamoko wrapper functions, and better memory handling of the transform objects. Another benefit that isn't realized yet is that this is a step towards breaking the renderers free of quake and quakeworld: although the clients don't actually use the scene yet, it will be a good place to store the rendering information (functions to run, etc). --- include/Makemodule.am | 1 + include/QF/scene/scene.h | 2 +- include/QF/scene/transform.h | 6 +- include/scn_internal.h | 14 +++++ libs/client/cl_temp_entities.c | 6 +- libs/scene/hierarchy.c | 13 ++-- libs/scene/scene.c | 6 +- libs/scene/test/test-hierarchy.c | 103 +++++++++++++++++-------------- libs/scene/transform.c | 18 ++++-- 9 files changed, 102 insertions(+), 67 deletions(-) create mode 100644 include/scn_internal.h diff --git a/include/Makemodule.am b/include/Makemodule.am index d405b745c..40c448f33 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -70,6 +70,7 @@ EXTRA_DIST += \ include/rua_internal.h \ include/sbar.h \ include/skin_stencil.h \ + include/scn_internal.h \ include/snd_internal.h \ include/sv_console.h \ include/varrays.h \ diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index c55ae8f35..e6262c008 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -48,7 +48,7 @@ typedef struct scene_s { scene_t *Scene_NewScene (void); void Scene_DeleteScene (scene_t *scene); struct entity_s *Scene_CreateEntity (scene_t *scene); -struct entity_s *Scene_GetEntity (scene_t *scene, int id); +struct entity_s *Scene_GetEntity (scene_t *scene, int id) __attribute__((pure)); void Scene_DestroyEntity (scene_t *scene, struct entity_s *entity); void Scene_FreeAllEntities (scene_t *scene); diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index fde6899ad..b9a909937 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -43,14 +43,16 @@ typedef struct transform_s { struct hierarchy_s *hierarchy; + struct scene_s *scene; ///< owning scene uint32_t index; ///< index in hierarchy int32_t id; ///< scene id } transform_t; -transform_t *Transform_New (transform_t *parent); +transform_t *Transform_New (struct scene_s *scene, transform_t *parent); /* Deletes all child transforms, and transform names */ void Transform_Delete (transform_t *transform); -transform_t *Transform_NewNamed (transform_t *parent, const char *name); +transform_t *Transform_NewNamed (struct scene_s *scene, transform_t *parent, + const char *name); uint32_t Transform_ChildCount (const transform_t *transform) __attribute__((pure)); transform_t *Transform_GetChild (const transform_t *transform, uint32_t childIndex) __attribute__((pure)); diff --git a/include/scn_internal.h b/include/scn_internal.h new file mode 100644 index 000000000..14faaa3ed --- /dev/null +++ b/include/scn_internal.h @@ -0,0 +1,14 @@ +#ifndef __scn_internal_h +#define __scn_internal_h + +#include "QF/progs.h" +#include "QF/scene/entity.h" +#include "QF/scene/scene.h" +#include "QF/scene/transform.h" + +typedef struct scene_resources_s { + PR_RESMAP (entity_t) entities; + PR_RESMAP (transform_t) transforms; +} scene_resources_t; + +#endif//__scn_internal_h diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 9ce856d70..7683586d7 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -46,6 +46,7 @@ #include "QF/plugin/vid_render.h" //FIXME #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "client/effects.h" #include "client/entities.h" @@ -85,6 +86,7 @@ typedef struct tent_obj_s { static PR_RESMAP (tent_t) temp_entities; static PR_RESMAP (tent_obj_t) tent_objects; +static scene_t *scene; static tent_obj_t *cl_beams; static tent_obj_t *cl_explosions; @@ -135,6 +137,8 @@ CL_TEnts_Precache (int phase) void CL_TEnts_Init (void) { + scene = Scene_NewScene (); + QFS_GamedirCallback (CL_TEnts_Precache); CL_TEnts_Precache (1); for (int i = 0; i < 360; i++) { @@ -151,7 +155,7 @@ CL_Init_Entity (entity_t *ent) } memset (ent, 0, sizeof (*ent)); - ent->transform = Transform_New (0); + ent->transform = Transform_New (scene, 0); ent->renderer.skin = 0; QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); ent->animation.pose1 = ent->animation.pose2 = -1; diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 43c3ea598..2e7ccaf47 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -38,6 +38,8 @@ #include "QF/scene/hierarchy.h" #include "QF/scene/transform.h" +#include "scn_internal.h" + #if defined(_WIN32) && !defined(_WIN64) // FIXME (maybe) this is a hack to make DARRAY arrrays 16-byte aligned on // 32-bit systems (in particular for this case, windows) as the vectors and @@ -430,11 +432,12 @@ Hierarchy_New (size_t grow, int createRoot) void Hierarchy_Delete (hierarchy_t *hierarchy) { - for (size_t i = 0; i < hierarchy->transform.size; i++) { - free (hierarchy->transform.a[i]); - } - for (size_t i = 0; i < hierarchy->name.size; i++) { - free (hierarchy->name.a[i]); + if (hierarchy->transform.size) { + scene_resources_t *res = hierarchy->transform.a[0]->scene->resources; + + for (size_t i = 0; i < hierarchy->transform.size; i++) { + PR_RESFREE (res->transforms, hierarchy->transform.a[i]); + } } DARRAY_CLEAR (&hierarchy->transform); DARRAY_CLEAR (&hierarchy->entity); diff --git a/libs/scene/scene.c b/libs/scene/scene.c index b7bc2d50b..10cfb3237 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -42,9 +42,7 @@ #include "QF/scene/scene.h" #include "QF/scene/transform.h" -typedef struct scene_resources_s { - PR_RESMAP (entity_t) entities; -} scene_resources_t; +#include "scn_internal.h" scene_t * Scene_NewScene (void) @@ -84,7 +82,7 @@ Scene_CreateEntity (scene_t *scene) scene_resources_t *res = scene->resources; entity_t *ent = PR_RESNEW_NC (res->entities); - ent->transform = Transform_New (0); + ent->transform = Transform_New (scene, 0); ent->id = PR_RESINDEX (res->entities, ent); hierarchy_t *h = ent->transform->hierarchy; diff --git a/libs/scene/test/test-hierarchy.c b/libs/scene/test/test-hierarchy.c index b6a3c0ca8..c8adb529e 100644 --- a/libs/scene/test/test-hierarchy.c +++ b/libs/scene/test/test-hierarchy.c @@ -7,8 +7,11 @@ #include #include "QF/scene/hierarchy.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" +scene_t *scene; + // NOTE: these are the columns of the matrix! (not that it matters for a // symmetrical matrix, but...) mat4f_t identity = { @@ -112,7 +115,7 @@ check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex, static int test_single_transform (void) { - transform_t *transform = Transform_New (0); + transform_t *transform = Transform_New (scene, 0); hierarchy_t *h; if (!transform) { @@ -149,8 +152,8 @@ test_single_transform (void) static int test_parent_child_init (void) { - transform_t *parent = Transform_New (0); - transform_t *child = Transform_New (parent); + transform_t *parent = Transform_New (scene, 0); + transform_t *child = Transform_New (scene, parent); if (parent->hierarchy != child->hierarchy) { printf ("parent and child transforms have separate hierarchies\n"); @@ -200,8 +203,8 @@ test_parent_child_init (void) static int test_parent_child_setparent (void) { - transform_t *parent = Transform_New (0); - transform_t *child = Transform_New (0); + transform_t *parent = Transform_New (scene, 0); + transform_t *child = Transform_New (scene, 0); Transform_SetName (parent, "parent"); Transform_SetName (child, "child"); @@ -267,17 +270,17 @@ test_build_hierarchy (void) { printf ("test_build_hierarchy\n"); - transform_t *root = Transform_NewNamed (0, "root"); - transform_t *A = Transform_NewNamed (root, "A"); - transform_t *B = Transform_NewNamed (root, "B"); - transform_t *C = Transform_NewNamed (root, "C"); + transform_t *root = Transform_NewNamed (scene, 0, "root"); + transform_t *A = Transform_NewNamed (scene, root, "A"); + transform_t *B = Transform_NewNamed (scene, root, "B"); + transform_t *C = Transform_NewNamed (scene, root, "C"); if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } if (!check_indices (A, 1, 0, 4, 0)) { return 1; } if (!check_indices (B, 2, 0, 4, 0)) { return 1; } if (!check_indices (C, 3, 0, 4, 0)) { return 1; } - transform_t *B1 = Transform_NewNamed (B, "B1"); + transform_t *B1 = Transform_NewNamed (scene, B, "B1"); if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 0)) { return 1; } @@ -285,7 +288,7 @@ test_build_hierarchy (void) if (!check_indices ( C, 3, 0, 5, 0)) { return 1; } if (!check_indices (B1, 4, 2, 5, 0)) { return 1; } - transform_t *A1 = Transform_NewNamed (A, "A1"); + transform_t *A1 = Transform_NewNamed (scene, A, "A1"); if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 1)) { return 1; } @@ -293,11 +296,11 @@ test_build_hierarchy (void) if (!check_indices ( C, 3, 0, 6, 0)) { return 1; } if (!check_indices (A1, 4, 1, 6, 0)) { return 1; } if (!check_indices (B1, 5, 2, 6, 0)) { return 1; } - transform_t *A1a = Transform_NewNamed (A1, "A1a"); - transform_t *B2 = Transform_NewNamed (B, "B2"); - transform_t *A2 = Transform_NewNamed (A, "A2"); - transform_t *B3 = Transform_NewNamed (B, "B3"); - transform_t *B2a = Transform_NewNamed (B2, "B2a"); + transform_t *A1a = Transform_NewNamed (scene, A1, "A1a"); + transform_t *B2 = Transform_NewNamed (scene, B, "B2"); + transform_t *A2 = Transform_NewNamed (scene, A, "A2"); + transform_t *B3 = Transform_NewNamed (scene, B, "B3"); + transform_t *B2a = Transform_NewNamed (scene, B2, "B2a"); if (!check_hierarchy_size (root->hierarchy, 11)) { return 1; } @@ -313,7 +316,7 @@ test_build_hierarchy (void) if (!check_indices (A1a, 9, 4, 11, 0)) { return 1; } if (!check_indices (B2a, 10, 7, 11, 0)) { return 1; } - transform_t *D = Transform_NewNamed (root, "D"); + transform_t *D = Transform_NewNamed (scene, root, "D"); if (!check_hierarchy_size (root->hierarchy, 12)) { return 1; } @@ -331,7 +334,7 @@ test_build_hierarchy (void) if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; } dump_hierarchy (root->hierarchy); - transform_t *C1 = Transform_NewNamed (C, "C1"); + transform_t *C1 = Transform_NewNamed (scene, C, "C1"); dump_hierarchy (root->hierarchy); if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; } @@ -360,19 +363,19 @@ test_build_hierarchy2 (void) { printf ("test_build_hierarchy2\n"); - transform_t *root = Transform_NewNamed (0, "root"); - transform_t *A = Transform_NewNamed (root, "A"); - transform_t *B = Transform_NewNamed (root, "B"); - transform_t *C = Transform_NewNamed (root, "C"); - transform_t *B1 = Transform_NewNamed (B, "B1"); - transform_t *A1 = Transform_NewNamed (A, "A1"); - transform_t *A1a = Transform_NewNamed (A1, "A1a"); - transform_t *B2 = Transform_NewNamed (B, "B2"); - transform_t *A2 = Transform_NewNamed (A, "A2"); - transform_t *B3 = Transform_NewNamed (B, "B3"); - transform_t *B2a = Transform_NewNamed (B2, "B2a"); - transform_t *D = Transform_NewNamed (root, "D"); - transform_t *C1 = Transform_NewNamed (C, "C1"); + transform_t *root = Transform_NewNamed (scene, 0, "root"); + transform_t *A = Transform_NewNamed (scene, root, "A"); + transform_t *B = Transform_NewNamed (scene, root, "B"); + transform_t *C = Transform_NewNamed (scene, root, "C"); + transform_t *B1 = Transform_NewNamed (scene, B, "B1"); + transform_t *A1 = Transform_NewNamed (scene, A, "A1"); + transform_t *A1a = Transform_NewNamed (scene, A1, "A1a"); + transform_t *B2 = Transform_NewNamed (scene, B, "B2"); + transform_t *A2 = Transform_NewNamed (scene, A, "A2"); + transform_t *B3 = Transform_NewNamed (scene, B, "B3"); + transform_t *B2a = Transform_NewNamed (scene, B2, "B2a"); + transform_t *D = Transform_NewNamed (scene, root, "D"); + transform_t *C1 = Transform_NewNamed (scene, C, "C1"); if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; } @@ -390,18 +393,18 @@ test_build_hierarchy2 (void) if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } - transform_t *T = Transform_NewNamed (0, "T"); - transform_t *X = Transform_NewNamed (T, "X"); - transform_t *Y = Transform_NewNamed (T, "Y"); - transform_t *Z = Transform_NewNamed (T, "Z"); - transform_t *Y1 = Transform_NewNamed (Y, "Y1"); - transform_t *X1 = Transform_NewNamed (X, "X1"); - transform_t *X1a = Transform_NewNamed (X1, "X1a"); - transform_t *Y2 = Transform_NewNamed (Y, "Y2"); - transform_t *X2 = Transform_NewNamed (X, "X2"); - transform_t *Y3 = Transform_NewNamed (Y, "Y3"); - transform_t *Y2a = Transform_NewNamed (Y2, "Y2a"); - transform_t *Z1 = Transform_NewNamed (Z, "Z1"); + transform_t *T = Transform_NewNamed (scene, 0, "T"); + transform_t *X = Transform_NewNamed (scene, T, "X"); + transform_t *Y = Transform_NewNamed (scene, T, "Y"); + transform_t *Z = Transform_NewNamed (scene, T, "Z"); + transform_t *Y1 = Transform_NewNamed (scene, Y, "Y1"); + transform_t *X1 = Transform_NewNamed (scene, X, "X1"); + transform_t *X1a = Transform_NewNamed (scene, X1, "X1a"); + transform_t *Y2 = Transform_NewNamed (scene, Y, "Y2"); + transform_t *X2 = Transform_NewNamed (scene, X, "X2"); + transform_t *Y3 = Transform_NewNamed (scene, Y, "Y3"); + transform_t *Y2a = Transform_NewNamed (scene, Y2, "Y2a"); + transform_t *Z1 = Transform_NewNamed (scene, Z, "Z1"); dump_hierarchy (T->hierarchy); if (!check_hierarchy_size (T->hierarchy, 12)) { return 1; } @@ -510,11 +513,11 @@ check_vector (const transform_t *transform, static int test_frames (void) { - transform_t *root = Transform_NewNamed (0, "root"); - transform_t *A = Transform_NewNamed (root, "A"); - transform_t *B = Transform_NewNamed (root, "B"); - transform_t *A1 = Transform_NewNamed (A, "A1"); - transform_t *B1 = Transform_NewNamed (B, "B1"); + transform_t *root = Transform_NewNamed (scene, 0, "root"); + transform_t *A = Transform_NewNamed (scene, root, "A"); + transform_t *B = Transform_NewNamed (scene, root, "B"); + transform_t *A1 = Transform_NewNamed (scene, A, "A1"); + transform_t *B1 = Transform_NewNamed (scene, B, "B1"); Transform_SetLocalPosition (root, (vec4f_t) { 0, 0, 1, 1 }); Transform_SetLocalPosition (A, (vec4f_t) { 1, 0, 0, 1 }); @@ -699,6 +702,8 @@ test_frames (void) int main (void) { + scene = Scene_NewScene (); + if (test_single_transform ()) { return 1; } if (test_parent_child_init ()) { return 1; } if (test_parent_child_setparent ()) { return 1; } @@ -706,5 +711,7 @@ main (void) if (test_build_hierarchy2 ()) { return 1; } if (test_frames ()) { return 1; } + Scene_DeleteScene (scene); + return 0; } diff --git a/libs/scene/transform.c b/libs/scene/transform.c index 5983d83bb..dbb2a6009 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -36,13 +36,19 @@ #endif #include "QF/scene/hierarchy.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" -transform_t * -Transform_New (transform_t *parent) -{ - transform_t *transform = malloc (sizeof (transform_t)); +#include "scn_internal.h" +transform_t * +Transform_New (scene_t *scene, transform_t *parent) +{ + scene_resources_t *res = scene->resources; + transform_t *transform = PR_RESNEW_NC (res->transforms); + + transform->scene = scene; + transform->id = PR_RESINDEX (res->transforms, transform); if (parent) { transform->hierarchy = parent->hierarchy; transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0, @@ -68,9 +74,9 @@ Transform_Delete (transform_t *transform) } transform_t * -Transform_NewNamed (transform_t *parent, const char *name) +Transform_NewNamed (scene_t *scene, transform_t *parent, const char *name) { - transform_t *transform = Transform_New (parent); + transform_t *transform = Transform_New (scene, parent); Transform_SetName (transform, name); return transform; }