[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).
This commit is contained in:
Bill Currie 2022-02-14 20:01:36 +09:00
parent f0c35e541a
commit ba3879c6e0
9 changed files with 102 additions and 67 deletions

View file

@ -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 \

View file

@ -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);

View file

@ -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));

14
include/scn_internal.h Normal file
View file

@ -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

View file

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

View file

@ -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);

View file

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

View file

@ -7,8 +7,11 @@
#include <unistd.h>
#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;
}

View file

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