From 7b756cc336f076fe95deb59847492b4127f82132 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 17 Feb 2024 13:08:35 -0800 Subject: Introduce Model. --- game/src/plugins/viewer.c | 46 ++++++++++++++++++++++++++++++------------- gfx/CMakeLists.txt | 1 + gfx/include/gfx/asset.h | 15 ++++++++------ gfx/include/gfx/scene.h | 1 + gfx/include/gfx/scene/model.h | 11 +++++++++++ gfx/include/gfx/scene/node.h | 17 +++++++++++++++- gfx/include/gfx/scene/scene.h | 3 --- gfx/include/gfx/sizes.h | 3 +++ gfx/src/asset/asset_cache.c | 42 ++++++++++++++++++--------------------- gfx/src/asset/asset_cache.h | 10 ++++++++-- gfx/src/asset/scene.c | 32 ++++++++++++++++-------------- gfx/src/asset/scene.h | 13 ++++-------- gfx/src/renderer/renderer.c | 14 +++++++++++-- gfx/src/scene/model.c | 41 ++++++++++++++++++++++++++++++++++++++ gfx/src/scene/model_impl.h | 17 ++++++++++++++++ gfx/src/scene/node.c | 46 +++++++++++++++++++++++++++++++++++-------- gfx/src/scene/node_impl.h | 1 + gfx/src/scene/scene.c | 19 ------------------ gfx/src/scene/scene_memory.c | 9 +++++++++ gfx/src/scene/scene_memory.h | 2 +- gfx/src/scene/types.h | 1 + 21 files changed, 241 insertions(+), 103 deletions(-) create mode 100644 gfx/include/gfx/scene/model.h create mode 100644 gfx/src/scene/model.c create mode 100644 gfx/src/scene/model_impl.h diff --git a/game/src/plugins/viewer.c b/game/src/plugins/viewer.c index 40213e4..dd7f451 100644 --- a/game/src/plugins/viewer.c +++ b/game/src/plugins/viewer.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -26,6 +25,7 @@ static const char* GIRL = struct State { Scene* scene; + Model* model; SceneCamera* camera; }; @@ -65,8 +65,8 @@ static SceneNode* load_skyquad(Gfx* gfx, SceneNode* root) { } /// Load the 3D scene. -static SceneNode* load_scene( - Game* game, State* state, const char* scene_filepath) { +/// Return the loaded model. +static Model* load_scene(Game* game, State* state, const char* scene_filepath) { assert(game); assert(game->gfx); assert(state); @@ -81,17 +81,22 @@ static SceneNode* load_scene( return 0; // test } - SceneNode* scene_node = gfx_load_scene( - game->gfx, sky_light_node, - &(LoadSceneCmd){ + Model* model = gfx_load_model( + game->gfx, + &(LoadModelCmd){ .origin = AssetFromFile, .filepath = mstring_make(scene_filepath)}); - if (!scene_node) { + if (!model) { return 0; } + SceneNode* model_node = gfx_make_model_node(model); + if (!model_node) { + return 0; + } + gfx_set_node_parent(model_node, sky_light_node); gfx_log_node_hierarchy(root); - return scene_node; + return model; } bool init(Game* game, State** pp_state) { @@ -115,13 +120,13 @@ bool init(Game* game, State** pp_state) { // Usage: const char* scene_filepath = argc > 1 ? argv[1] : DEFAULT_SCENE_FILE; - SceneNode* node = load_scene(game, state, scene_filepath); - if (!node) { + state->model = load_scene(game, state, scene_filepath); + if (!state->model) { goto cleanup; } - if (gfx_get_node_type(node) == AnimaNode) { - Anima* anima = gfx_get_node_anima(node); + Anima* anima = gfx_get_model_anima(state->model); + if (anima) { gfx_play_animation( anima, &(AnimationPlaySettings){.name = "Walk", .loop = true}); } @@ -156,7 +161,13 @@ void update(Game* game, State* state, double t, double dt) { assert(state->scene); assert(state->camera); - gfx_animate_scene(state->scene, (R)t); + // TODO: Move this to some sort of update_scene(). Note that models do not + // need to be animated if they are not visible to the camera. The camera + // update also should happen first. + Anima* anima = gfx_get_model_anima(state->model); + if (anima) { + gfx_update_animation(anima, (R)t); + } const vec3 orbit_point = vec3_make(0, 2, 0); Camera* camera = gfx_get_camera_camera(state->camera); @@ -171,7 +182,14 @@ void update(Game* game, State* state, double t, double dt) { static void render_bounding_boxes_rec(ImmRenderer* imm, const SceneNode* node) { assert(imm); assert(node); - if (gfx_get_node_type(node) == ObjectNode) { + + const NodeType node_type = gfx_get_node_type(node); + + if (node_type == ModelNode) { + const Model* model = gfx_get_node_model(node); + const SceneNode* root = gfx_get_model_root(model); + render_bounding_boxes_rec(imm, root); + } else if (node_type == ObjectNode) { // TODO: Look at the scene log. The JointNodes are detached from the // ObjectNodes. This is why the boxes are not being transformed as expected // here. Anima needs to animate boxes? Use OOBB in addition to AABB? diff --git a/gfx/CMakeLists.txt b/gfx/CMakeLists.txt index 2d83a7c..b423990 100644 --- a/gfx/CMakeLists.txt +++ b/gfx/CMakeLists.txt @@ -51,6 +51,7 @@ add_library(gfx SHARED src/scene/light.c src/scene/material.c src/scene/mesh.c + src/scene/model.c src/scene/node.c src/scene/object.c src/scene/scene.c diff --git a/gfx/include/gfx/asset.h b/gfx/include/gfx/asset.h index c2bac57..c5cc5f8 100644 --- a/gfx/include/gfx/asset.h +++ b/gfx/include/gfx/asset.h @@ -6,7 +6,7 @@ #include typedef struct Gfx Gfx; -typedef struct SceneNode SceneNode; +typedef struct Model Model; typedef struct ShaderProgram ShaderProgram; typedef struct Texture Texture; @@ -67,12 +67,12 @@ typedef struct LoadTextureCmd { } data; } LoadTextureCmd; -/// Describes a command to load a scene. +/// Describes a command to load a model. /// -/// |shader| is an optional shader program assigned to the loaded scene objects. +/// |shader| is an optional shader program assigned to the loaded model objects. /// If no shader is given, a Cook-Torrance shader based on the object's /// characteristics (presence of normals, tangents, etc) is assigned. -typedef struct LoadSceneCmd { +typedef struct LoadModelCmd { AssetOrigin origin; union { struct { @@ -84,7 +84,10 @@ typedef struct LoadSceneCmd { }; }; ShaderProgram* shader; -} LoadSceneCmd; +} LoadModelCmd; + +// TODO: We should return const resources. If the client wants a mutable copy, +// then let them clone the resource. /// Load a scene. /// @@ -94,7 +97,7 @@ typedef struct LoadSceneCmd { /// null. /// /// Currently only supports the GLTF format. -SceneNode* gfx_load_scene(Gfx*, SceneNode* parent_node, const LoadSceneCmd*); +Model* gfx_load_model(Gfx*, const LoadModelCmd*); /// Load a texture. Texture* gfx_load_texture(Gfx*, const LoadTextureCmd*); diff --git a/gfx/include/gfx/scene.h b/gfx/include/gfx/scene.h index 1d74679..abcaa70 100644 --- a/gfx/include/gfx/scene.h +++ b/gfx/include/gfx/scene.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/gfx/include/gfx/scene/model.h b/gfx/include/gfx/scene/model.h new file mode 100644 index 0000000..f4972a9 --- /dev/null +++ b/gfx/include/gfx/scene/model.h @@ -0,0 +1,11 @@ +#pragma once + +typedef struct Anima Anima; +typedef struct Model Model; +typedef struct SceneNode SceneNode; + +/// Return the model's anima, or null if the model is not animated. +Anima* gfx_get_model_anima(Model*); + +/// Return the model's root node. +const SceneNode* gfx_get_model_root(const Model*); diff --git a/gfx/include/gfx/scene/node.h b/gfx/include/gfx/scene/node.h index 7976ae8..3877670 100644 --- a/gfx/include/gfx/scene/node.h +++ b/gfx/include/gfx/scene/node.h @@ -9,6 +9,7 @@ typedef struct Anima Anima; typedef struct Light Light; +typedef struct Model Model; typedef struct SceneCamera SceneCamera; typedef struct SceneObject SceneObject; @@ -21,7 +22,8 @@ typedef enum NodeType { AnimaNode, CameraNode, LightNode, - ObjectNode + ModelNode, + ObjectNode, } NodeType; /// A node in the scene graph. @@ -49,6 +51,9 @@ SceneNode* gfx_make_camera_node(SceneCamera*); /// Create a new light node. SceneNode* gfx_make_light_node(Light*); +/// Create a new model node. +SceneNode* gfx_make_model_node(Model*); + /// Create a new object node. SceneNode* gfx_make_object_node(SceneObject*); @@ -61,6 +66,9 @@ void gfx_construct_camera_node(SceneNode*, SceneCamera*); /// Make the node a light node. void gfx_construct_light_node(SceneNode*, Light*); +/// Make the node a model node. +void gfx_construct_model_node(SceneNode*, Model*); + /// Make the node an object node. void gfx_construct_object_node(SceneNode*, SceneObject*); @@ -75,6 +83,8 @@ void gfx_destroy_node(SceneNode**); // Getters. // ----------------------------------------------------------------------------- +// TODO: Review constness of getters here. + /// Return the node's type. NodeType gfx_get_node_type(const SceneNode*); @@ -93,6 +103,11 @@ SceneCamera* gfx_get_node_camera(const SceneNode* node); /// The node must be of type LightNode. Light* gfx_get_node_light(const SceneNode*); +/// Get the node's model. +/// +/// The node must be of type ModelNode. +Model* gfx_get_node_model(const SceneNode*); + /// Get the node's scene object. /// /// The node must be of type ObjectNode. diff --git a/gfx/include/gfx/scene/scene.h b/gfx/include/gfx/scene/scene.h index f5c9ddf..0d96210 100644 --- a/gfx/include/gfx/scene/scene.h +++ b/gfx/include/gfx/scene/scene.h @@ -19,6 +19,3 @@ void gfx_destroy_scene(Scene**); /// Get the scene's root node. SceneNode* gfx_get_scene_root(Scene*); - -/// Update the scene's animations. -void gfx_animate_scene(Scene*, R t); diff --git a/gfx/include/gfx/sizes.h b/gfx/include/gfx/sizes.h index b6f47ef..076113c 100644 --- a/gfx/include/gfx/sizes.h +++ b/gfx/include/gfx/sizes.h @@ -18,6 +18,9 @@ /// Maximum number of mesh links. #define GFX_MAX_NUM_MESH_LINKS 1024 +/// Maximum number of models. +#define GFX_MAX_NUM_MODELS 64 + /// Maximum number of joints per skeleton. #define GFX_MAX_NUM_JOINTS 96 diff --git a/gfx/src/asset/asset_cache.c b/gfx/src/asset/asset_cache.c index 0075d41..037f62b 100644 --- a/gfx/src/asset/asset_cache.c +++ b/gfx/src/asset/asset_cache.c @@ -4,15 +4,12 @@ #include "texture.h" #include #include -#include #include -#include "scene/node_impl.h" - #include #include -static Hash calc_scene_hash(const LoadSceneCmd* cmd) { +static Hash calc_model_hash(const LoadModelCmd* cmd) { assert(cmd); switch (cmd->origin) { case AssetFromFile: @@ -20,7 +17,7 @@ static Hash calc_scene_hash(const LoadSceneCmd* cmd) { case AssetFromMemory: return (Hash)cmd->data; } - FAIL("Unhandled scene asset origin"); + FAIL("Unhandled model asset origin"); return 0; } @@ -74,7 +71,7 @@ static Asset* lookup_cache(AssetCache* cache, Hash hash) { return 0; } -static void log_scene_cache_hit(const LoadSceneCmd* cmd, Hash hash) { +static void log_model_cache_hit(const LoadModelCmd* cmd, Hash hash) { assert(cmd); switch (cmd->origin) { case AssetFromFile: @@ -88,7 +85,7 @@ static void log_scene_cache_hit(const LoadSceneCmd* cmd, Hash hash) { } } -static void log_scene_loaded(const LoadSceneCmd* cmd) { +static void log_model_loaded(const LoadModelCmd* cmd) { assert(cmd); switch (cmd->origin) { case AssetFromFile: @@ -115,32 +112,31 @@ void gfx_destroy_asset_cache(AssetCache* cache) { mempool_del(&cache->assets); } -SceneNode* gfx_load_scene( - Gfx* gfx, SceneNode* parent_node, const LoadSceneCmd* cmd) { +Model* gfx_load_model(Gfx* gfx, const LoadModelCmd* cmd) { assert(gfx); AssetCache* cache = gfx_get_asset_cache(gfx); // First search for the asset in the cache. - const uint64_t hash = calc_scene_hash(cmd); + const uint64_t hash = calc_model_hash(cmd); Asset* asset = lookup_cache(cache, hash); if (asset) { - log_scene_cache_hit(cmd, hash); - return (SceneNode*)asset; + log_model_cache_hit(cmd, hash); + return asset->model; } // Asset not found in the cache. // Load it, insert it into the cache, and return it. - SceneNode* node = gfx_scene_load(gfx, parent_node, cmd); - if (node) { + Model* model = gfx_model_load(gfx, cmd); + if (model) { *(Asset*)mempool_alloc(&cache->assets) = (Asset){ - .type = SceneAsset, - .hash = hash, - .data = node, + .type = ModelAsset, + .hash = hash, + .model = model, }; - log_scene_loaded(cmd); + log_model_loaded(cmd); } - return node; + return model; } Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) { @@ -153,7 +149,7 @@ Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) { const uint64_t hash = calc_texture_hash(cmd); Asset* asset = lookup_cache(cache, hash); if (asset) { - return (Texture*)asset; + return asset->texture; } // Asset not found in the cache. @@ -162,9 +158,9 @@ Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) { Texture* texture = gfx_texture_load(render_backend, cmd); if (texture) { *(Asset*)mempool_alloc(&cache->assets) = (Asset){ - .type = TextureAsset, - .hash = hash, - .data = texture, + .type = TextureAsset, + .hash = hash, + .texture = texture, }; } return texture; diff --git a/gfx/src/asset/asset_cache.h b/gfx/src/asset/asset_cache.h index 04baa51..22300fd 100644 --- a/gfx/src/asset/asset_cache.h +++ b/gfx/src/asset/asset_cache.h @@ -5,17 +5,23 @@ #include #include +typedef struct Model Model; +typedef struct Texture Texture; + typedef uint64_t Hash; typedef enum AssetType { - SceneAsset, + ModelAsset, TextureAsset, } AssetType; typedef struct Asset { AssetType type; Hash hash; - void* data; + union { + Model* model; + Texture* texture; + }; } Asset; DEF_MEMPOOL(asset_pool, Asset, GFX_MAX_NUM_ASSETS) diff --git a/gfx/src/asset/scene.c b/gfx/src/asset/scene.c index ef2328c..290ade9 100644 --- a/gfx/src/asset/scene.c +++ b/gfx/src/asset/scene.c @@ -94,6 +94,8 @@ #include "gfx/sizes.h" #include "gfx/util/shader.h" +#include "scene/model_impl.h" + #include "cstring.h" #include "error.h" #include "log/log.h" @@ -1487,16 +1489,16 @@ static void load_nodes( } // SceneNode. } -/// Load all scenes from the glTF file into the given gfx Scene. +/// Load all scenes from the glTF file. /// /// If the scene is loaded from memory, set filepath = null. /// /// This function ignores the many scenes and default scene of the glTF spec -/// and instead just loads all scenes into a single gfx Scene. -static SceneNode* load_scene( - cgltf_data* data, Gfx* gfx, SceneNode* parent_node, const mstring* filepath, - ShaderProgram* shader, const cgltfTangentBuffer* cgltf_tangent_buffers, - cgltf_size num_tangent_buffers) { +/// and instead just loads all scenes into a single Gfx Scene. +static Model* load_scene( + cgltf_data* data, Gfx* gfx, const mstring* filepath, ShaderProgram* shader, + const cgltfTangentBuffer* cgltf_tangent_buffers, + cgltf_size num_tangent_buffers) { // In a GLTF scene, buffers can be shared among meshes, meshes among nodes, // etc. Each object is referenced by its index in the relevant array. Here we // do a button-up construction, first allocating our own graphics objects in @@ -1540,6 +1542,7 @@ static SceneNode* load_scene( SceneNode** scene_nodes = 0; Anima* anima = 0; SceneNode* root_node = 0; + Model* model = 0; tangent_buffers = calloc(num_tangent_buffers, sizeof(Buffer*)); buffers = calloc(data->buffers_count, sizeof(Buffer*)); @@ -1619,13 +1622,14 @@ static SceneNode* load_scene( anima = gfx_make_anima(anima_desc); gfx_construct_anima_node(root_node, anima); } - gfx_set_node_parent(root_node, parent_node); // The root node becomes the root of all scene nodes. load_nodes(data, root_node, scene_objects, scene_cameras, anima, scene_nodes); // TODO: Clean up scene nodes that correspond to joints in the glTF. + model = gfx_make_model(root_node); + success = true; cleanup: @@ -1734,16 +1738,14 @@ cleanup: gfx_destroy_anima(&anima); } } - return root_node; + return model; } -SceneNode* gfx_scene_load( - Gfx* gfx, SceneNode* parent_node, const LoadSceneCmd* cmd) { +Model* gfx_model_load(Gfx* gfx, const LoadModelCmd* cmd) { assert(gfx); - assert(parent_node); assert(cmd); - SceneNode* scene_node = 0; + Model* model = 0; cgltf_options options = {0}; cgltf_data* data = NULL; @@ -1775,8 +1777,8 @@ SceneNode* gfx_scene_load( cgltf_compute_tangents( &options, data, &tangent_buffers, &num_tangent_buffers); - scene_node = load_scene( - data, gfx, parent_node, &cmd->filepath, cmd->shader, tangent_buffers, + model = load_scene( + data, gfx, &cmd->filepath, cmd->shader, tangent_buffers, num_tangent_buffers); cleanup: @@ -1786,5 +1788,5 @@ cleanup: if (tangent_buffers) { free(tangent_buffers); } - return scene_node; + return model; } diff --git a/gfx/src/asset/scene.h b/gfx/src/asset/scene.h index 5c47196..d6399b1 100644 --- a/gfx/src/asset/scene.h +++ b/gfx/src/asset/scene.h @@ -3,15 +3,10 @@ #include -typedef struct Gfx Gfx; -typedef struct SceneNode SceneNode; +typedef struct Gfx Gfx; +typedef struct Model Model; -/// Load a scene. -/// -/// Return the top-level node under which scene elements are rooted. -/// -/// |parent_node| is made the parent of the returned top-level node. It may be -/// null. +/// Load a model. /// /// Currently only supports the GLTF format. -SceneNode* gfx_scene_load(Gfx*, SceneNode* parent_node, const LoadSceneCmd*); +Model* gfx_model_load(Gfx*, const LoadModelCmd*); diff --git a/gfx/src/renderer/renderer.c b/gfx/src/renderer/renderer.c index 5cc06d6..30704e3 100644 --- a/gfx/src/renderer/renderer.c +++ b/gfx/src/renderer/renderer.c @@ -1,9 +1,11 @@ #include "renderer_impl.h" +#include "scene/animation_impl.h" #include "scene/camera_impl.h" #include "scene/light_impl.h" #include "scene/material_impl.h" #include "scene/mesh_impl.h" +#include "scene/model_impl.h" #include "scene/node_impl.h" #include "scene/object_impl.h" #include "scene/scene_impl.h" @@ -207,10 +209,12 @@ static void draw_recursively( assert(state); const mat4 node_transform = mat4_mul(parent_transform, node->transform); - // Activate light. + // Anima. if (node->type == AnimaNode) { state->anima = gfx_get_node_anima(node); - } else if (node->type == LightNode) { + } + // Activate light. + else if (node->type == LightNode) { Light* light = mem_get_light(node->light); assert(light); @@ -222,6 +226,12 @@ static void draw_recursively( state->environment_light = light; } } + // Model. + else if (node->type == ModelNode) { + const Model* model = gfx_get_node_model(node); + const SceneNode* root = mem_get_node(model->root); + draw_recursively(state, parent_transform, root); + } // Render object. else if (node->type == ObjectNode) { const SceneObject* object = mem_get_object(node->object); diff --git a/gfx/src/scene/model.c b/gfx/src/scene/model.c new file mode 100644 index 0000000..89ff0c3 --- /dev/null +++ b/gfx/src/scene/model.c @@ -0,0 +1,41 @@ +#include "model_impl.h" + +#include + +#include "scene_memory.h" + +#include + +Model* gfx_make_model(const SceneNode* root) { + assert(root); + + Model* model = mem_alloc_model(); + model->root = mem_get_node_index(root); + return model; +} + +void gfx_del_model(Model** model) { + assert(model); + + if (*model) { + SceneNode* root = mem_get_node((*model)->root); + gfx_destroy_node(&root); + *model = 0; + } +} + +Anima* gfx_get_model_anima(Model* model) { + assert(model); + + SceneNode* root = mem_get_node(model->root); + if (gfx_get_node_type(root) == AnimaNode) { + return gfx_get_node_anima(root); + } else { + return 0; + } +} + +const SceneNode* gfx_get_model_root(const Model* model) { + assert(model); + return mem_get_node(model->root); +} diff --git a/gfx/src/scene/model_impl.h b/gfx/src/scene/model_impl.h new file mode 100644 index 0000000..a99d32c --- /dev/null +++ b/gfx/src/scene/model_impl.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "scene_memory.h" + +/// Model. +typedef struct Model { + node_idx root; + node_idx parent; // Parent SceneNode. +} Model; + +/// Create a new model. +Model* gfx_make_model(const SceneNode* root); + +/// Destroy the model. +void gfx_del_model(Model**); diff --git a/gfx/src/scene/node.c b/gfx/src/scene/node.c index 1a68216..c48d3dd 100644 --- a/gfx/src/scene/node.c +++ b/gfx/src/scene/node.c @@ -1,16 +1,18 @@ #include "node_impl.h" +#include "animation_impl.h" #include "camera_impl.h" #include "light_impl.h" +#include "model_impl.h" #include "object_impl.h" #include "scene_graph.h" #include "scene_memory.h" +#include "gfx_assert.h" + #include #include -#include - static void scene_node_make(SceneNode* node) { assert(node); node->type = LogicalNode; @@ -50,6 +52,15 @@ SceneNode* gfx_make_light_node(Light* light) { return node; } +SceneNode* gfx_make_model_node(Model* model) { + assert(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; +} + SceneNode* gfx_make_object_node(SceneObject* object) { assert(object); SceneNode* node = gfx_make_node(); @@ -70,29 +81,33 @@ static void free_node_resource(SceneNode* node) { Anima* anima = mem_get_anima(node->anima); anima->parent.val = 0; gfx_destroy_anima(&anima); - break; + return; } case CameraNode: { SceneCamera* camera = mem_get_camera(node->camera); camera->parent.val = 0; gfx_destroy_camera(&camera); - break; + return; } case LightNode: { Light* light = mem_get_light(node->light); light->parent.val = 0; gfx_destroy_light(&light); - break; + return; + } + case ModelNode: { + return; // Model data is owned by the asset cache. } case ObjectNode: { SceneObject* object = mem_get_object(node->object); object->parent.val = 0; gfx_destroy_object(&object); - break; + return; } case LogicalNode: - break; // Logical nodes have no resource. + return; // Logical nodes have no resource. } + FAIL("unhandled node type"); } void gfx_construct_anima_node(SceneNode* node, Anima* anima) { @@ -124,6 +139,15 @@ void gfx_construct_light_node(SceneNode* node, Light* light) { light->parent = mem_get_node_index(node); } +void gfx_construct_model_node(SceneNode* node, Model* model) { + assert(node); + assert(model); + free_node_resource(node); + node->type = ModelNode; + node->model = mem_get_model_index(model); + model->parent = mem_get_node_index(node); +} + void gfx_construct_object_node(SceneNode* node, SceneObject* object) { assert(node); assert(object); @@ -197,6 +221,10 @@ Light* gfx_get_node_light(const SceneNode* node) { NODE_GET(node, light, LightNode); } +Model* gfx_get_node_model(const SceneNode* node) { + NODE_GET(node, model, ModelNode); +} + SceneObject* gfx_get_node_object(const SceneNode* node) { NODE_GET(node, object, ObjectNode); } @@ -283,10 +311,12 @@ static const char* get_node_type_str(NodeType type) { return "CameraNode"; case LightNode: return "LightNode"; + case ModelNode: + return "ModelNode"; case ObjectNode: return "ObjectNode"; } - assert(false); + FAIL("Unhandled node type"); return ""; } diff --git a/gfx/src/scene/node_impl.h b/gfx/src/scene/node_impl.h index 4592fce..cabdc60 100644 --- a/gfx/src/scene/node_impl.h +++ b/gfx/src/scene/node_impl.h @@ -17,6 +17,7 @@ typedef struct SceneNode { anima_idx anima; camera_idx camera; light_idx light; + model_idx model; object_idx object; }; mat4 transform; // Transformation for this node and its children. diff --git a/gfx/src/scene/scene.c b/gfx/src/scene/scene.c index a6801ba..54452dd 100644 --- a/gfx/src/scene/scene.c +++ b/gfx/src/scene/scene.c @@ -23,22 +23,3 @@ SceneNode* gfx_get_scene_root(Scene* scene) { assert(scene); return scene->root; } - -static void gfx_animate_node(SceneNode* node, R t) { - assert(node); - - if (gfx_get_node_type(node) == AnimaNode) { - gfx_update_animation(gfx_get_node_anima(node), t); - } - - for (NodeIter it = gfx_get_node_child(node); it; - it = gfx_get_next_child(it)) { - gfx_animate_node(gfx_get_iter_node_mut(it), t); - } -} - -void gfx_animate_scene(Scene* scene, R t) { - assert(scene); - SceneNode* node = gfx_get_scene_root(scene); - gfx_animate_node(node, t); -} diff --git a/gfx/src/scene/scene_memory.c b/gfx/src/scene/scene_memory.c index 2b900b9..3030a8a 100644 --- a/gfx/src/scene/scene_memory.c +++ b/gfx/src/scene/scene_memory.c @@ -7,6 +7,7 @@ #include "light_impl.h" #include "material_impl.h" #include "mesh_impl.h" +#include "model_impl.h" #include "node_impl.h" #include "object_impl.h" #include "scene_impl.h" @@ -20,6 +21,7 @@ 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) DEF_MEMPOOL(mesh_link_pool, MeshLink, GFX_MAX_NUM_MESH_LINKS) +DEF_MEMPOOL(model_pool, Model, GFX_MAX_NUM_MODELS) DEF_MEMPOOL(node_pool, SceneNode, GFX_MAX_NUM_NODES) DEF_MEMPOOL(object_pool, SceneObject, GFX_MAX_NUM_OBJECTS) DEF_MEMPOOL(scene_pool, Scene, GFX_MAX_NUM_SCENES) @@ -36,6 +38,7 @@ typedef struct SceneMemory { material_pool materials; mesh_pool meshs; // Purposeful typo to make the PLURAL() macro work. mesh_link_pool mesh_links; + model_pool models; node_pool nodes; object_pool objects; scene_pool scenes; @@ -61,6 +64,7 @@ void scene_mem_init() { mempool_make(&mem.materials); mempool_make(&mem.meshs); mempool_make(&mem.mesh_links); + mempool_make(&mem.models); mempool_make(&mem.nodes); mempool_make(&mem.objects); mempool_make(&mem.scenes); @@ -75,6 +79,7 @@ void scene_mem_init() { ALLOC_DUMMY(&mem.materials); ALLOC_DUMMY(&mem.meshs); ALLOC_DUMMY(&mem.mesh_links); + ALLOC_DUMMY(&mem.models); ALLOC_DUMMY(&mem.nodes); ALLOC_DUMMY(&mem.objects); ALLOC_DUMMY(&mem.scenes); @@ -92,6 +97,9 @@ void scene_mem_destroy() { } \ }) + // Models contain scene elements. Destruction is handled by the remainder of + // scene destructionb elow. + // // First destroy the scenes. This will recursively destroy the scene's nodes // and their objects and avoid a double-free when we then destroy any stray // scene elements. @@ -135,6 +143,7 @@ DEF_MEMORY(light, Light) DEF_MEMORY(material, Material) DEF_MEMORY(mesh, Mesh) DEF_MEMORY(mesh_link, MeshLink) +DEF_MEMORY(model, Model) DEF_MEMORY(node, SceneNode) DEF_MEMORY(object, SceneObject) DEF_MEMORY(scene, Scene) diff --git a/gfx/src/scene/scene_memory.h b/gfx/src/scene/scene_memory.h index 04dbd20..d175cba 100644 --- a/gfx/src/scene/scene_memory.h +++ b/gfx/src/scene/scene_memory.h @@ -1,7 +1,6 @@ /// Memory management of scene objects. #pragma once -#include "animation_impl.h" #include "types.h" /// Initialize scene memory. @@ -33,6 +32,7 @@ DECL_MEMORY(light, Light) DECL_MEMORY(material, Material) DECL_MEMORY(mesh, Mesh) DECL_MEMORY(mesh_link, MeshLink) +DECL_MEMORY(model, Model) DECL_MEMORY(node, SceneNode) DECL_MEMORY(object, SceneObject) DECL_MEMORY(scene, Scene) diff --git a/gfx/src/scene/types.h b/gfx/src/scene/types.h index cd87430..9752bcf 100644 --- a/gfx/src/scene/types.h +++ b/gfx/src/scene/types.h @@ -18,6 +18,7 @@ DEF_STRONG_INDEX(light, gfx_idx) DEF_STRONG_INDEX(material, gfx_idx) DEF_STRONG_INDEX(mesh, gfx_idx) DEF_STRONG_INDEX(mesh_link, gfx_idx) +DEF_STRONG_INDEX(model, gfx_idx) DEF_STRONG_INDEX(node, gfx_idx) DEF_STRONG_INDEX(object, gfx_idx) DEF_STRONG_INDEX(scene, gfx_idx) -- cgit v1.2.3