From 440b292c39162284a447b34d3a692143af9fbc87 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Thu, 30 Oct 2025 17:21:22 -0700 Subject: - Replace SceneCamera with Camera. - Remove backpointer from scene types to node to decouple underlying types from the scene graph. --- src/asset/asset_cache.c | 1 - src/asset/model.c | 34 +++++++++------------------------- src/memory.c | 13 +++++++------ src/memory.h | 10 ++++++---- src/render/llr.c | 3 --- src/render/llr_impl.h | 1 - src/render/renderer.c | 13 ++++++------- src/scene/animation.c | 10 ++-------- src/scene/animation_impl.h | 30 ++++++++++++++---------------- src/scene/camera.c | 28 ++++++---------------------- src/scene/camera_impl.h | 12 ------------ src/scene/model_impl.h | 1 - src/scene/node.c | 32 +++++++++++--------------------- src/scene/node_impl.h | 4 +--- src/scene/object.c | 4 ---- src/scene/object_impl.h | 4 +--- src/scene/scene_graph.h | 2 +- 17 files changed, 64 insertions(+), 138 deletions(-) delete mode 100644 src/scene/camera_impl.h (limited to 'src') diff --git a/src/asset/asset_cache.c b/src/asset/asset_cache.c index a364330..191a5fd 100644 --- a/src/asset/asset_cache.c +++ b/src/asset/asset_cache.c @@ -167,7 +167,6 @@ static Model* clone_model(const Model* model) { SceneNode* root_copy = gfx_clone_scene_shallow(root); root_copy->anima = mem_get_anima_index(anima_copy); - anima_copy->parent = mem_get_node_index(root_copy); Model* copy = mem_alloc_model(); copy->root = mem_get_node_index(root_copy); diff --git a/src/asset/model.c b/src/asset/model.c index ccda27d..df116fb 100644 --- a/src/asset/model.c +++ b/src/asset/model.c @@ -1555,7 +1555,7 @@ static void remove_joint_nodes( /// and instead just loads all nodes into a single gfx Scene. static void load_nodes( const cgltf_data* data, SceneNode* root_node, SceneObject** objects, - SceneCamera** cameras, const Anima* anima, SceneNode** nodes) { + const Anima* anima, SceneNode** nodes) { // Note that with glTF 2.0, nodes do not form a DAG / scene graph but a // disjoint union of strict trees: // @@ -1570,7 +1570,6 @@ static void load_nodes( assert(data); assert(root_node); assert(objects); - assert(cameras); assert(nodes); cgltf_size next_camera = 0; @@ -1579,7 +1578,7 @@ static void load_nodes( for (cgltf_size n = 0; n < data->nodes_count; ++n) { const cgltf_node* node = &data->nodes[n]; - // Add SceneObject, SceneCamera or Lights. + // Add SceneObject, Camera or Lights. // TODO: Handle lights once they are implemented in the gfx library. assert(!nodes[n]); if (node->mesh) { @@ -1599,29 +1598,27 @@ static void load_nodes( } else if (node->camera) { assert(next_camera < data->cameras_count); - Camera camera; const cgltf_camera* cam = node->camera; // TODO: We could define a function load_cameras() the same way we load // every mesh and then remove this ad-hoc loading of cameras here, as well // as remove 'next_camera'. + Camera* camera = gfx_make_camera(); switch (cam->type) { case cgltf_camera_type_orthographic: - camera = camera_orthographic( + *camera = camera_orthographic( 0, cam->data.orthographic.xmag, 0, cam->data.orthographic.ymag, cam->data.orthographic.znear, cam->data.orthographic.zfar); break; case cgltf_camera_type_perspective: - camera = camera_perspective( + *camera = camera_perspective( cam->data.perspective.yfov, cam->data.perspective.aspect_ratio, cam->data.perspective.znear, cam->data.perspective.zfar); break; case cgltf_camera_type_invalid: break; } - - gfx_set_camera_camera(cameras[next_camera], &camera); - nodes[n] = gfx_make_camera_node(cameras[next_camera]); + nodes[n] = gfx_make_camera_node(camera); ++next_camera; } else { // TODO: implementation for missing node types. @@ -1727,7 +1724,6 @@ static Model* load_scene( Mesh** meshes = 0; AnimaDesc* anima_desc = 0; SceneObject** scene_objects = 0; - SceneCamera** scene_cameras = 0; SceneNode** scene_nodes = 0; Anima* anima = 0; SceneNode* root_node = 0; @@ -1740,8 +1736,7 @@ static Model* load_scene( geometries = calloc(primitive_count, sizeof(Geometry*)); meshes = calloc(primitive_count, sizeof(Mesh*)); scene_objects = calloc(data->meshes_count, sizeof(SceneObject*)); - scene_cameras = calloc(data->cameras_count, sizeof(SceneCamera**)); - scene_nodes = calloc(data->nodes_count, sizeof(SceneNode**)); + scene_nodes = calloc(data->nodes_count, sizeof(SceneNode*)); // A glTF scene does not necessarily have textures. Materials can be given // as constants, for example. if (data->textures_count > 0) { @@ -1750,8 +1745,7 @@ static Model* load_scene( if (!buffers || !tangent_buffers || ((data->textures_count > 0) && !load_texture_cmds) || !textures || - !materials || !geometries || !meshes || !scene_objects || - !scene_cameras || !scene_nodes) { + !materials || !geometries || !meshes || !scene_objects || !scene_nodes) { goto cleanup; } @@ -1809,7 +1803,7 @@ static Model* load_scene( assert(root_node); // The root node becomes the root of all scene nodes. - load_nodes(data, root_node, scene_objects, scene_cameras, anima, scene_nodes); + load_nodes(data, root_node, scene_objects, anima, scene_nodes); model = gfx_make_model(root_node); @@ -1887,16 +1881,6 @@ cleanup: } free(scene_objects); } - if (scene_cameras) { - if (!success) { - for (cgltf_size i = 0; i < data->cameras_count; ++i) { - if (scene_cameras[i]) { - gfx_destroy_camera(&scene_cameras[i]); - } - } - } - free(scene_cameras); - } if (scene_nodes) { if (!success) { for (cgltf_size i = 0; i < data->nodes_count; ++i) { diff --git a/src/memory.c b/src/memory.c index a68bc2b..3481791 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,21 +1,22 @@ #include "memory.h" +#include #include #include "render/llr_impl.h" #include "scene/animation_impl.h" -#include "scene/camera_impl.h" #include "scene/model_impl.h" #include "scene/node_impl.h" #include "scene/object_impl.h" #include "scene/scene_impl.h" #include +#include #include DEF_MEMPOOL(anima_pool, Anima, GFX_MAX_NUM_ANIMAS) DEF_MEMPOOL(animation_pool, Animation, GFX_MAX_NUM_ANIMATIONS) -DEF_MEMPOOL(camera_pool, SceneCamera, GFX_MAX_NUM_CAMERAS) +DEF_MEMPOOL(camera_pool, Camera, GFX_MAX_NUM_CAMERAS) DEF_MEMPOOL(light_pool, Light, GFX_MAX_NUM_LIGHTS) DEF_MEMPOOL(material_pool, Material, GFX_MAX_NUM_MATERIALS) DEF_MEMPOOL(mesh_pool, Mesh, GFX_MAX_NUM_MESHES) @@ -56,7 +57,7 @@ static SceneMemory mem; #define PLURAL(name) name##s #define MEM_FIELD(name) mem.PLURAL(name) -void scene_mem_init() { +void scene_mem_init(void) { mempool_make(&mem.animas); mempool_make(&mem.animations); mempool_make(&mem.cameras); @@ -86,7 +87,7 @@ void scene_mem_init() { ALLOC_DUMMY(&mem.skeletons); } -void scene_mem_destroy() { +void scene_mem_destroy(void) { // NOTE: the dummy objects are not constructed, so the destruction code below // always skips index 0. (I don't really like the conditional inside the loop, // but this gets the job done without having to specialize the loop macro.) @@ -148,7 +149,7 @@ void scene_mem_destroy() { #define DEF_MEMORY(NAME, TYPE) \ /* xyz* mem_alloc_xyz(); */ \ - TYPE* mem_alloc_##NAME() { return mempool_alloc(&MEM_FIELD(NAME)); } \ + TYPE* mem_alloc_##NAME(void) { return mempool_alloc(&MEM_FIELD(NAME)); } \ /* void mem_free_xyz(xyz**); */ \ void mem_free_##NAME(TYPE** obj) { mempool_free(&MEM_FIELD(NAME), obj); } \ /* xyz* mem_get_xyz(xyz_idx); */ \ @@ -164,7 +165,7 @@ void scene_mem_destroy() { DEF_MEMORY(anima, Anima) DEF_MEMORY(animation, Animation) -DEF_MEMORY(camera, SceneCamera) +DEF_MEMORY(camera, Camera) DEF_MEMORY(light, Light) DEF_MEMORY(material, Material) DEF_MEMORY(mesh, Mesh) diff --git a/src/memory.h b/src/memory.h index 366c6e4..624216d 100644 --- a/src/memory.h +++ b/src/memory.h @@ -3,21 +3,23 @@ #include "scene/types.h" +typedef struct Camera Camera; + /// Initialize scene memory. /// /// The scene memory guarantees that every object maps to an index different /// than 0. This way, 0 can be used as a special index to denote "no value". -void scene_mem_init(); +void scene_mem_init(void); /// Destroy the scene memory and all allocated objects. -void scene_mem_destroy(); +void scene_mem_destroy(void); #define NAMED_INDEX(name) name##_idx #define DECL_MEMORY(name, type) \ typedef struct type type; \ /* xyz* mem_alloc_xyz() */ \ - type* mem_alloc_##name(); \ + type* mem_alloc_##name(void); \ /* mem_free_xyz(xyz**) */ \ void mem_free_##name(type**); \ /* xyz* mem_get_xyz(xyz_idx); */ \ @@ -27,7 +29,7 @@ void scene_mem_destroy(); DECL_MEMORY(anima, Anima) DECL_MEMORY(animation, Animation) -DECL_MEMORY(camera, SceneCamera) +DECL_MEMORY(camera, Camera) DECL_MEMORY(light, Light) DECL_MEMORY(material, Material) DECL_MEMORY(mesh, Mesh) diff --git a/src/render/llr.c b/src/render/llr.c index a1b37be..189041a 100644 --- a/src/render/llr.c +++ b/src/render/llr.c @@ -46,9 +46,6 @@ Light* gfx_make_light(const LightDesc* desc) { void gfx_destroy_light(Light** light) { assert(light); if (*light) { - if ((*light)->parent.val) { - gfx_del_node((*light)->parent); - } mem_free_light(light); } } diff --git a/src/render/llr_impl.h b/src/render/llr_impl.h index 319441c..1c08b03 100644 --- a/src/render/llr_impl.h +++ b/src/render/llr_impl.h @@ -34,7 +34,6 @@ typedef struct Light { union { EnvironmentLight environment; }; - node_idx parent; // Parent SceneNode. } Light; typedef struct Material { diff --git a/src/render/renderer.c b/src/render/renderer.c index eca7551..385a8c1 100644 --- a/src/render/renderer.c +++ b/src/render/renderer.c @@ -3,7 +3,6 @@ #include "llr_impl.h" #include "memory.h" #include "scene/animation_impl.h" -#include "scene/camera_impl.h" #include "scene/model_impl.h" #include "scene/node_impl.h" #include "scene/object_impl.h" @@ -192,9 +191,9 @@ void gfx_render_scene(Renderer* renderer, const RenderSceneParams* params) { ShaderProgram* const shader = load_shader(renderer, params->mode); - const Scene* scene = params->scene; - const SceneCamera* camera = params->camera; - GfxCore* const gfxcore = renderer->gfxcore; + const Scene* scene = params->scene; + const Camera* camera = params->camera; + GfxCore* const gfxcore = renderer->gfxcore; int x, y, width, height; gfx_get_viewport(gfxcore, &x, &y, &width, &height); @@ -207,12 +206,12 @@ void gfx_render_scene(Renderer* renderer, const RenderSceneParams* params) { .shader = shader, .scene = scene}; - gfx_llr_set_camera(renderer->llr, &camera->camera); + gfx_llr_set_camera(renderer->llr, camera); gfx_llr_set_aspect(renderer->llr, aspect); draw_recursively(&state, mat4_id(), scene->root); } -static void update_rec(SceneNode* node, const SceneCamera* camera, R t) { +static void update_rec(SceneNode* node, const Camera* camera, R t) { assert(node); assert(camera); @@ -237,7 +236,7 @@ static void update_rec(SceneNode* node, const SceneCamera* camera, R t) { } } -void gfx_update(Scene* scene, const SceneCamera* camera, R t) { +void gfx_update(Scene* scene, const Camera* camera, R t) { assert(scene); assert(camera); diff --git a/src/scene/animation.c b/src/scene/animation.c index 601c400..a498961 100644 --- a/src/scene/animation.c +++ b/src/scene/animation.c @@ -204,10 +204,6 @@ void gfx_destroy_anima(Anima** anima) { mem_free_animation(&animation); } - if ((*anima)->parent.val) { - gfx_del_node((*anima)->parent); - } - mem_free_anima(anima); } } @@ -450,10 +446,8 @@ void gfx_update_animation(Anima* anima, R t) { // which we have constructed to be the common root of all skeletons. // // This procedure touches every joint exactly once. - SceneNode* root_node = mem_get_node(anima->parent); - // LOGD("Root: %u, child: %u", anima->parent.val, root->child.val); - const mat4 root_global_transform = gfx_get_node_global_transform(root_node); - const mat4 root_inv_global_transform = mat4_inverse(root_global_transform); + const mat4 root_global_transform = mat4_id(); + const mat4 root_inv_global_transform = mat4_id(); Joint* root_joint = get_anima_root_joint(anima); compute_joint_matrices_rec( diff --git a/src/scene/animation_impl.h b/src/scene/animation_impl.h index 4408158..ef1492c 100644 --- a/src/scene/animation_impl.h +++ b/src/scene/animation_impl.h @@ -12,7 +12,6 @@ #include #include -#include typedef struct Buffer Buffer; @@ -24,24 +23,24 @@ typedef struct Buffer Buffer; /// Joints are mutable and store the transform and joint matrices that result /// from animation, aside from the inverse bind matrix. typedef struct Joint { - joint_idx child; /// First child Joint; index into Anima's joints. - joint_idx next; /// Next sibling Joint; index into Anima's joints. - mat4 transform; /// Local transform relative to parent. - mat4 inv_bind_matrix; /// Transforms the mesh into the joint's local space. - mat4 joint_matrix; /// inv(global) * global joint transform * inv(bind). - aabb3 box; /// Bounding box of vertices affected by joint. + joint_idx child; // First child Joint; index into Anima's joints. + joint_idx next; // Next sibling Joint; index into Anima's joints. + mat4 transform; // Local transform relative to parent. + mat4 inv_bind_matrix; // Transforms the mesh into the joint's local space. + mat4 joint_matrix; // inv(global) * global joint transform * inv(bind). + aabb3 box; // Bounding box of vertices affected by joint. } Joint; /// Animation skeleton. typedef struct Skeleton { skeleton_idx next; size_t num_joints; - joint_idx joints[GFX_MAX_NUM_JOINTS]; /// Indices into Anima's joints array. + joint_idx joints[GFX_MAX_NUM_JOINTS]; // Indices into Anima's joints array. } Skeleton; /// A keyframe of animation. typedef struct Keyframe { - R time; /// Start time in [0, end animation time] + R time; // Start time in [0, end animation time] union { vec3 translation; quat rotation; @@ -50,7 +49,7 @@ typedef struct Keyframe { /// Animation channel. typedef struct Channel { - joint_idx target; /// Index into Anima's joints array. + joint_idx target; // Index into Anima's joints array. ChannelType type; AnimationInterpolation interpolation; size_t num_keyframes; @@ -89,10 +88,9 @@ typedef struct AnimationState { /// have no parent (a skeleton need not have its own root and can be a set of /// disjoint node hierarchies). typedef struct Anima { - node_idx parent; /// Parent SceneNode. - skeleton_idx skeleton; /// Index of first skeleton. - animation_idx animation; /// Index of first animation. - AnimationState state; /// Current animation state. - size_t num_joints; /// Number of actual joints in the array. - Joint joints[GFX_MAX_NUM_JOINTS]; /// Shared by all skeletons. + skeleton_idx skeleton; // Index of first skeleton. + animation_idx animation; // Index of first animation. + AnimationState state; // Current animation state. + size_t num_joints; // Number of actual joints in the array. + Joint joints[GFX_MAX_NUM_JOINTS]; // Shared by all skeletons. } Anima; diff --git a/src/scene/camera.c b/src/scene/camera.c index bb073ba..475101d 100644 --- a/src/scene/camera.c +++ b/src/scene/camera.c @@ -1,37 +1,21 @@ -#include "camera_impl.h" +#include #include "memory.h" -#include "node_impl.h" #include +#include -SceneCamera* gfx_make_camera() { - SceneCamera* camera = mem_alloc_camera(); - - camera->camera = camera_perspective( +Camera* gfx_make_camera() { + Camera* camera = mem_alloc_camera(); + *camera = camera_perspective( /*fovy=*/90.0 * TO_RAD, /*aspect=*/16.0 / 9.0, /*near=*/0.1, /*far=*/1000); - return camera; } -void gfx_destroy_camera(SceneCamera** camera) { +void gfx_destroy_camera(Camera** camera) { assert(camera); if (*camera) { - if ((*camera)->parent.val) { - gfx_del_node((*camera)->parent); - } mem_free_camera(camera); } } - -void gfx_set_camera_camera(SceneCamera* scene_camera, Camera* camera) { - assert(scene_camera); - assert(camera); - scene_camera->camera = *camera; -} - -Camera* gfx_get_camera_camera(SceneCamera* camera) { - assert(camera); - return &camera->camera; -} diff --git a/src/scene/camera_impl.h b/src/scene/camera_impl.h deleted file mode 100644 index 20c3890..0000000 --- a/src/scene/camera_impl.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include - -#include "types.h" - -#include - -typedef struct SceneCamera { - Camera camera; - node_idx parent; // Parent SceneNode. -} SceneCamera; diff --git a/src/scene/model_impl.h b/src/scene/model_impl.h index 39ac27f..079aede 100644 --- a/src/scene/model_impl.h +++ b/src/scene/model_impl.h @@ -7,7 +7,6 @@ /// Model. typedef struct Model { node_idx root; - node_idx parent; // Parent SceneNode. } Model; /// Create a new model. diff --git a/src/scene/node.c b/src/scene/node.c index 7cc315c..7032324 100644 --- a/src/scene/node.c +++ b/src/scene/node.c @@ -1,15 +1,15 @@ #include "node_impl.h" #include "animation_impl.h" -#include "camera_impl.h" #include "memory.h" -#include "model_impl.h" #include "object_impl.h" #include "render/llr_impl.h" #include "scene_graph.h" #include "gfx_assert.h" +#include + #include #include @@ -19,7 +19,7 @@ static void scene_node_make(SceneNode* node) { node->transform = mat4_id(); } -SceneNode* gfx_make_node() { +SceneNode* gfx_make_node(void) { SceneNode* node = mem_alloc_node(); scene_node_make(node); return node; @@ -30,16 +30,14 @@ SceneNode* gfx_make_anima_node(Anima* anima) { SceneNode* node = gfx_make_node(); node->type = AnimaNode; node->anima = mem_get_anima_index(anima); - anima->parent = mem_get_node_index(node); return node; } -SceneNode* gfx_make_camera_node(SceneCamera* camera) { +SceneNode* gfx_make_camera_node(Camera* camera) { assert(camera); SceneNode* node = gfx_make_node(); node->type = CameraNode; node->camera = mem_get_camera_index(camera); - camera->parent = mem_get_node_index(node); return node; } @@ -48,7 +46,6 @@ SceneNode* gfx_make_light_node(Light* light) { SceneNode* node = gfx_make_node(); node->type = LightNode; node->light = mem_get_light_index(light); - light->parent = mem_get_node_index(node); return node; } @@ -57,7 +54,6 @@ SceneNode* gfx_make_model_node(Model* model) { SceneNode* node = gfx_make_node(); node->type = ModelNode; node->model = mem_get_model_index(model); - model->parent = mem_get_node_index(node); return node; } @@ -66,7 +62,6 @@ SceneNode* gfx_make_object_node(SceneObject* object) { SceneNode* node = gfx_make_node(); node->type = ObjectNode; node->object = mem_get_object_index(object); - object->parent = mem_get_node_index(node); return node; } @@ -74,24 +69,19 @@ SceneNode* gfx_make_object_node(SceneObject* object) { static void free_node_resource(SceneNode* node) { assert(node); - // Set the resource's parent node back to 0 to avoid a recursive call into - // gfx_del_node(). switch (node->type) { case AnimaNode: { - Anima* anima = mem_get_anima(node->anima); - anima->parent.val = 0; + Anima* anima = mem_get_anima(node->anima); gfx_destroy_anima(&anima); return; } case CameraNode: { - SceneCamera* camera = mem_get_camera(node->camera); - camera->parent.val = 0; + Camera* camera = mem_get_camera(node->camera); gfx_destroy_camera(&camera); return; } case LightNode: { - Light* light = mem_get_light(node->light); - light->parent.val = 0; + Light* light = mem_get_light(node->light); gfx_destroy_light(&light); return; } @@ -100,13 +90,13 @@ static void free_node_resource(SceneNode* node) { } case ObjectNode: { SceneObject* object = mem_get_object(node->object); - object->parent.val = 0; gfx_destroy_object(&object); return; } - case LogicalNode: + case LogicalNode: { return; // Logical nodes have no resource. } + } FAIL("unhandled node type"); } @@ -170,11 +160,11 @@ Anima* gfx_get_node_anima_mut(SceneNode* node) { NODE_GET(node, anima, AnimaNode); } -const SceneCamera* gfx_get_node_camera(const SceneNode* node) { +const Camera* gfx_get_node_camera(const SceneNode* node) { NODE_GET(node, camera, CameraNode); } -SceneCamera* gfx_get_node_camera_mut(SceneNode* node) { +Camera* gfx_get_node_camera_mut(SceneNode* node) { NODE_GET(node, camera, CameraNode); } diff --git a/src/scene/node_impl.h b/src/scene/node_impl.h index fb88bd5..15ee232 100644 --- a/src/scene/node_impl.h +++ b/src/scene/node_impl.h @@ -4,6 +4,7 @@ #include "types.h" +#include #include /// Scene node. @@ -12,9 +13,6 @@ /// together form a strict tree hierarchy and not a more general DAG. typedef struct SceneNode { NodeType type; - // TODO: Inline the actual object here and get rid of the indirection and the - // extra pools? The "scene camera" is kind of a useless data structure, for - // example. union { anima_idx anima; camera_idx camera; diff --git a/src/scene/object.c b/src/scene/object.c index d1f355c..7004ce1 100644 --- a/src/scene/object.c +++ b/src/scene/object.c @@ -57,11 +57,7 @@ SceneObject* gfx_make_object(const ObjectDesc* desc) { void gfx_destroy_object(SceneObject** object) { assert(object); - if (*object) { - if ((*object)->parent.val) { - gfx_del_node((*object)->parent); - } mem_free_object(object); } } diff --git a/src/scene/object_impl.h b/src/scene/object_impl.h index e864e53..b7a0752 100644 --- a/src/scene/object_impl.h +++ b/src/scene/object_impl.h @@ -19,7 +19,5 @@ typedef struct MeshLink { typedef struct SceneObject { mesh_link_idx mesh_link; /// First MeshLink in the list. skeleton_idx skeleton; /// 0 for static objects. - // TODO: Can we just store node indices in nodes, not the contained object? - node_idx parent; /// Parent SceneNode. - aabb3 box; + aabb3 box; } SceneObject; diff --git a/src/scene/scene_graph.h b/src/scene/scene_graph.h index e7135a4..36c3a98 100644 --- a/src/scene/scene_graph.h +++ b/src/scene/scene_graph.h @@ -20,7 +20,7 @@ #define MEM_GET_INDEX(ITEM) \ _Generic( \ (ITEM), \ - SceneCamera *: mem_get_camera_index, \ + Camera *: mem_get_camera_index, \ Material *: mem_get_material_index, \ Mesh *: mem_get_mesh_index, \ MeshLink *: mem_get_mesh_link_index, \ -- cgit v1.2.3