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; }