diff options
| author | 3gg <3gg@shellblade.net> | 2024-02-17 13:08:35 -0800 | 
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2024-02-17 13:08:35 -0800 | 
| commit | 7b756cc336f076fe95deb59847492b4127f82132 (patch) | |
| tree | 365fc9a388bff1d0d347b8e86ba6b8c97490d4fb | |
| parent | 13c7adb42168a566c97f36db76080d80e02a6aae (diff) | |
Introduce Model.
| -rw-r--r-- | game/src/plugins/viewer.c | 46 | ||||
| -rw-r--r-- | gfx/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | gfx/include/gfx/asset.h | 15 | ||||
| -rw-r--r-- | gfx/include/gfx/scene.h | 1 | ||||
| -rw-r--r-- | gfx/include/gfx/scene/model.h | 11 | ||||
| -rw-r--r-- | gfx/include/gfx/scene/node.h | 17 | ||||
| -rw-r--r-- | gfx/include/gfx/scene/scene.h | 3 | ||||
| -rw-r--r-- | gfx/include/gfx/sizes.h | 3 | ||||
| -rw-r--r-- | gfx/src/asset/asset_cache.c | 42 | ||||
| -rw-r--r-- | gfx/src/asset/asset_cache.h | 10 | ||||
| -rw-r--r-- | gfx/src/asset/scene.c | 32 | ||||
| -rw-r--r-- | gfx/src/asset/scene.h | 13 | ||||
| -rw-r--r-- | gfx/src/renderer/renderer.c | 14 | ||||
| -rw-r--r-- | gfx/src/scene/model.c | 41 | ||||
| -rw-r--r-- | gfx/src/scene/model_impl.h | 17 | ||||
| -rw-r--r-- | gfx/src/scene/node.c | 46 | ||||
| -rw-r--r-- | gfx/src/scene/node_impl.h | 1 | ||||
| -rw-r--r-- | gfx/src/scene/scene.c | 19 | ||||
| -rw-r--r-- | gfx/src/scene/scene_memory.c | 9 | ||||
| -rw-r--r-- | gfx/src/scene/scene_memory.h | 2 | ||||
| -rw-r--r-- | gfx/src/scene/types.h | 1 | 
21 files changed, 241 insertions, 103 deletions
| 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 @@ | |||
| 3 | #include <gfx/asset.h> | 3 | #include <gfx/asset.h> | 
| 4 | #include <gfx/renderer.h> | 4 | #include <gfx/renderer.h> | 
| 5 | #include <gfx/scene.h> | 5 | #include <gfx/scene.h> | 
| 6 | #include <gfx/scene/scene.h> | ||
| 7 | #include <gfx/util/skyquad.h> | 6 | #include <gfx/util/skyquad.h> | 
| 8 | #include <math/camera.h> | 7 | #include <math/camera.h> | 
| 9 | #include <math/spatial3.h> | 8 | #include <math/spatial3.h> | 
| @@ -26,6 +25,7 @@ static const char* GIRL = | |||
| 26 | 25 | ||
| 27 | struct State { | 26 | struct State { | 
| 28 | Scene* scene; | 27 | Scene* scene; | 
| 28 | Model* model; | ||
| 29 | SceneCamera* camera; | 29 | SceneCamera* camera; | 
| 30 | }; | 30 | }; | 
| 31 | 31 | ||
| @@ -65,8 +65,8 @@ static SceneNode* load_skyquad(Gfx* gfx, SceneNode* root) { | |||
| 65 | } | 65 | } | 
| 66 | 66 | ||
| 67 | /// Load the 3D scene. | 67 | /// Load the 3D scene. | 
| 68 | static SceneNode* load_scene( | 68 | /// Return the loaded model. | 
| 69 | Game* game, State* state, const char* scene_filepath) { | 69 | static Model* load_scene(Game* game, State* state, const char* scene_filepath) { | 
| 70 | assert(game); | 70 | assert(game); | 
| 71 | assert(game->gfx); | 71 | assert(game->gfx); | 
| 72 | assert(state); | 72 | assert(state); | 
| @@ -81,17 +81,22 @@ static SceneNode* load_scene( | |||
| 81 | return 0; // test | 81 | return 0; // test | 
| 82 | } | 82 | } | 
| 83 | 83 | ||
| 84 | SceneNode* scene_node = gfx_load_scene( | 84 | Model* model = gfx_load_model( | 
| 85 | game->gfx, sky_light_node, | 85 | game->gfx, | 
| 86 | &(LoadSceneCmd){ | 86 | &(LoadModelCmd){ | 
| 87 | .origin = AssetFromFile, .filepath = mstring_make(scene_filepath)}); | 87 | .origin = AssetFromFile, .filepath = mstring_make(scene_filepath)}); | 
| 88 | if (!scene_node) { | 88 | if (!model) { | 
| 89 | return 0; | 89 | return 0; | 
| 90 | } | 90 | } | 
| 91 | SceneNode* model_node = gfx_make_model_node(model); | ||
| 92 | if (!model_node) { | ||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | gfx_set_node_parent(model_node, sky_light_node); | ||
| 91 | 96 | ||
| 92 | gfx_log_node_hierarchy(root); | 97 | gfx_log_node_hierarchy(root); | 
| 93 | 98 | ||
| 94 | return scene_node; | 99 | return model; | 
| 95 | } | 100 | } | 
| 96 | 101 | ||
| 97 | bool init(Game* game, State** pp_state) { | 102 | bool init(Game* game, State** pp_state) { | 
| @@ -115,13 +120,13 @@ bool init(Game* game, State** pp_state) { | |||
| 115 | // Usage: <scene file> | 120 | // Usage: <scene file> | 
| 116 | const char* scene_filepath = argc > 1 ? argv[1] : DEFAULT_SCENE_FILE; | 121 | const char* scene_filepath = argc > 1 ? argv[1] : DEFAULT_SCENE_FILE; | 
| 117 | 122 | ||
| 118 | SceneNode* node = load_scene(game, state, scene_filepath); | 123 | state->model = load_scene(game, state, scene_filepath); | 
| 119 | if (!node) { | 124 | if (!state->model) { | 
| 120 | goto cleanup; | 125 | goto cleanup; | 
| 121 | } | 126 | } | 
| 122 | 127 | ||
| 123 | if (gfx_get_node_type(node) == AnimaNode) { | 128 | Anima* anima = gfx_get_model_anima(state->model); | 
| 124 | Anima* anima = gfx_get_node_anima(node); | 129 | if (anima) { | 
| 125 | gfx_play_animation( | 130 | gfx_play_animation( | 
| 126 | anima, &(AnimationPlaySettings){.name = "Walk", .loop = true}); | 131 | anima, &(AnimationPlaySettings){.name = "Walk", .loop = true}); | 
| 127 | } | 132 | } | 
| @@ -156,7 +161,13 @@ void update(Game* game, State* state, double t, double dt) { | |||
| 156 | assert(state->scene); | 161 | assert(state->scene); | 
| 157 | assert(state->camera); | 162 | assert(state->camera); | 
| 158 | 163 | ||
| 159 | gfx_animate_scene(state->scene, (R)t); | 164 | // TODO: Move this to some sort of update_scene(). Note that models do not | 
| 165 | // need to be animated if they are not visible to the camera. The camera | ||
| 166 | // update also should happen first. | ||
| 167 | Anima* anima = gfx_get_model_anima(state->model); | ||
| 168 | if (anima) { | ||
| 169 | gfx_update_animation(anima, (R)t); | ||
| 170 | } | ||
| 160 | 171 | ||
| 161 | const vec3 orbit_point = vec3_make(0, 2, 0); | 172 | const vec3 orbit_point = vec3_make(0, 2, 0); | 
| 162 | Camera* camera = gfx_get_camera_camera(state->camera); | 173 | Camera* camera = gfx_get_camera_camera(state->camera); | 
| @@ -171,7 +182,14 @@ void update(Game* game, State* state, double t, double dt) { | |||
| 171 | static void render_bounding_boxes_rec(ImmRenderer* imm, const SceneNode* node) { | 182 | static void render_bounding_boxes_rec(ImmRenderer* imm, const SceneNode* node) { | 
| 172 | assert(imm); | 183 | assert(imm); | 
| 173 | assert(node); | 184 | assert(node); | 
| 174 | if (gfx_get_node_type(node) == ObjectNode) { | 185 | |
| 186 | const NodeType node_type = gfx_get_node_type(node); | ||
| 187 | |||
| 188 | if (node_type == ModelNode) { | ||
| 189 | const Model* model = gfx_get_node_model(node); | ||
| 190 | const SceneNode* root = gfx_get_model_root(model); | ||
| 191 | render_bounding_boxes_rec(imm, root); | ||
| 192 | } else if (node_type == ObjectNode) { | ||
| 175 | // TODO: Look at the scene log. The JointNodes are detached from the | 193 | // TODO: Look at the scene log. The JointNodes are detached from the | 
| 176 | // ObjectNodes. This is why the boxes are not being transformed as expected | 194 | // ObjectNodes. This is why the boxes are not being transformed as expected | 
| 177 | // here. Anima needs to animate boxes? Use OOBB in addition to AABB? | 195 | // 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 | |||
| 51 | src/scene/light.c | 51 | src/scene/light.c | 
| 52 | src/scene/material.c | 52 | src/scene/material.c | 
| 53 | src/scene/mesh.c | 53 | src/scene/mesh.c | 
| 54 | src/scene/model.c | ||
| 54 | src/scene/node.c | 55 | src/scene/node.c | 
| 55 | src/scene/object.c | 56 | src/scene/object.c | 
| 56 | src/scene/scene.c | 57 | 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 @@ | |||
| 6 | #include <stddef.h> | 6 | #include <stddef.h> | 
| 7 | 7 | ||
| 8 | typedef struct Gfx Gfx; | 8 | typedef struct Gfx Gfx; | 
| 9 | typedef struct SceneNode SceneNode; | 9 | typedef struct Model Model; | 
| 10 | typedef struct ShaderProgram ShaderProgram; | 10 | typedef struct ShaderProgram ShaderProgram; | 
| 11 | typedef struct Texture Texture; | 11 | typedef struct Texture Texture; | 
| 12 | 12 | ||
| @@ -67,12 +67,12 @@ typedef struct LoadTextureCmd { | |||
| 67 | } data; | 67 | } data; | 
| 68 | } LoadTextureCmd; | 68 | } LoadTextureCmd; | 
| 69 | 69 | ||
| 70 | /// Describes a command to load a scene. | 70 | /// Describes a command to load a model. | 
| 71 | /// | 71 | /// | 
| 72 | /// |shader| is an optional shader program assigned to the loaded scene objects. | 72 | /// |shader| is an optional shader program assigned to the loaded model objects. | 
| 73 | /// If no shader is given, a Cook-Torrance shader based on the object's | 73 | /// If no shader is given, a Cook-Torrance shader based on the object's | 
| 74 | /// characteristics (presence of normals, tangents, etc) is assigned. | 74 | /// characteristics (presence of normals, tangents, etc) is assigned. | 
| 75 | typedef struct LoadSceneCmd { | 75 | typedef struct LoadModelCmd { | 
| 76 | AssetOrigin origin; | 76 | AssetOrigin origin; | 
| 77 | union { | 77 | union { | 
| 78 | struct { | 78 | struct { | 
| @@ -84,7 +84,10 @@ typedef struct LoadSceneCmd { | |||
| 84 | }; | 84 | }; | 
| 85 | }; | 85 | }; | 
| 86 | ShaderProgram* shader; | 86 | ShaderProgram* shader; | 
| 87 | } LoadSceneCmd; | 87 | } LoadModelCmd; | 
| 88 | |||
| 89 | // TODO: We should return const resources. If the client wants a mutable copy, | ||
| 90 | // then let them clone the resource. | ||
| 88 | 91 | ||
| 89 | /// Load a scene. | 92 | /// Load a scene. | 
| 90 | /// | 93 | /// | 
| @@ -94,7 +97,7 @@ typedef struct LoadSceneCmd { | |||
| 94 | /// null. | 97 | /// null. | 
| 95 | /// | 98 | /// | 
| 96 | /// Currently only supports the GLTF format. | 99 | /// Currently only supports the GLTF format. | 
| 97 | SceneNode* gfx_load_scene(Gfx*, SceneNode* parent_node, const LoadSceneCmd*); | 100 | Model* gfx_load_model(Gfx*, const LoadModelCmd*); | 
| 98 | 101 | ||
| 99 | /// Load a texture. | 102 | /// Load a texture. | 
| 100 | Texture* gfx_load_texture(Gfx*, const LoadTextureCmd*); | 103 | 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 @@ | |||
| 5 | #include <gfx/scene/light.h> | 5 | #include <gfx/scene/light.h> | 
| 6 | #include <gfx/scene/material.h> | 6 | #include <gfx/scene/material.h> | 
| 7 | #include <gfx/scene/mesh.h> | 7 | #include <gfx/scene/mesh.h> | 
| 8 | #include <gfx/scene/model.h> | ||
| 8 | #include <gfx/scene/node.h> | 9 | #include <gfx/scene/node.h> | 
| 9 | #include <gfx/scene/object.h> | 10 | #include <gfx/scene/object.h> | 
| 10 | #include <gfx/scene/scene.h> | 11 | #include <gfx/scene/scene.h> | 
| 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 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | typedef struct Anima Anima; | ||
| 4 | typedef struct Model Model; | ||
| 5 | typedef struct SceneNode SceneNode; | ||
| 6 | |||
| 7 | /// Return the model's anima, or null if the model is not animated. | ||
| 8 | Anima* gfx_get_model_anima(Model*); | ||
| 9 | |||
| 10 | /// Return the model's root node. | ||
| 11 | 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 @@ | |||
| 9 | 9 | ||
| 10 | typedef struct Anima Anima; | 10 | typedef struct Anima Anima; | 
| 11 | typedef struct Light Light; | 11 | typedef struct Light Light; | 
| 12 | typedef struct Model Model; | ||
| 12 | typedef struct SceneCamera SceneCamera; | 13 | typedef struct SceneCamera SceneCamera; | 
| 13 | typedef struct SceneObject SceneObject; | 14 | typedef struct SceneObject SceneObject; | 
| 14 | 15 | ||
| @@ -21,7 +22,8 @@ typedef enum NodeType { | |||
| 21 | AnimaNode, | 22 | AnimaNode, | 
| 22 | CameraNode, | 23 | CameraNode, | 
| 23 | LightNode, | 24 | LightNode, | 
| 24 | ObjectNode | 25 | ModelNode, | 
| 26 | ObjectNode, | ||
| 25 | } NodeType; | 27 | } NodeType; | 
| 26 | 28 | ||
| 27 | /// A node in the scene graph. | 29 | /// A node in the scene graph. | 
| @@ -49,6 +51,9 @@ SceneNode* gfx_make_camera_node(SceneCamera*); | |||
| 49 | /// Create a new light node. | 51 | /// Create a new light node. | 
| 50 | SceneNode* gfx_make_light_node(Light*); | 52 | SceneNode* gfx_make_light_node(Light*); | 
| 51 | 53 | ||
| 54 | /// Create a new model node. | ||
| 55 | SceneNode* gfx_make_model_node(Model*); | ||
| 56 | |||
| 52 | /// Create a new object node. | 57 | /// Create a new object node. | 
| 53 | SceneNode* gfx_make_object_node(SceneObject*); | 58 | SceneNode* gfx_make_object_node(SceneObject*); | 
| 54 | 59 | ||
| @@ -61,6 +66,9 @@ void gfx_construct_camera_node(SceneNode*, SceneCamera*); | |||
| 61 | /// Make the node a light node. | 66 | /// Make the node a light node. | 
| 62 | void gfx_construct_light_node(SceneNode*, Light*); | 67 | void gfx_construct_light_node(SceneNode*, Light*); | 
| 63 | 68 | ||
| 69 | /// Make the node a model node. | ||
| 70 | void gfx_construct_model_node(SceneNode*, Model*); | ||
| 71 | |||
| 64 | /// Make the node an object node. | 72 | /// Make the node an object node. | 
| 65 | void gfx_construct_object_node(SceneNode*, SceneObject*); | 73 | void gfx_construct_object_node(SceneNode*, SceneObject*); | 
| 66 | 74 | ||
| @@ -75,6 +83,8 @@ void gfx_destroy_node(SceneNode**); | |||
| 75 | // Getters. | 83 | // Getters. | 
| 76 | // ----------------------------------------------------------------------------- | 84 | // ----------------------------------------------------------------------------- | 
| 77 | 85 | ||
| 86 | // TODO: Review constness of getters here. | ||
| 87 | |||
| 78 | /// Return the node's type. | 88 | /// Return the node's type. | 
| 79 | NodeType gfx_get_node_type(const SceneNode*); | 89 | NodeType gfx_get_node_type(const SceneNode*); | 
| 80 | 90 | ||
| @@ -93,6 +103,11 @@ SceneCamera* gfx_get_node_camera(const SceneNode* node); | |||
| 93 | /// The node must be of type LightNode. | 103 | /// The node must be of type LightNode. | 
| 94 | Light* gfx_get_node_light(const SceneNode*); | 104 | Light* gfx_get_node_light(const SceneNode*); | 
| 95 | 105 | ||
| 106 | /// Get the node's model. | ||
| 107 | /// | ||
| 108 | /// The node must be of type ModelNode. | ||
| 109 | Model* gfx_get_node_model(const SceneNode*); | ||
| 110 | |||
| 96 | /// Get the node's scene object. | 111 | /// Get the node's scene object. | 
| 97 | /// | 112 | /// | 
| 98 | /// The node must be of type ObjectNode. | 113 | /// 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**); | |||
| 19 | 19 | ||
| 20 | /// Get the scene's root node. | 20 | /// Get the scene's root node. | 
| 21 | SceneNode* gfx_get_scene_root(Scene*); | 21 | SceneNode* gfx_get_scene_root(Scene*); | 
| 22 | |||
| 23 | /// Update the scene's animations. | ||
| 24 | 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 @@ | |||
| 18 | /// Maximum number of mesh links. | 18 | /// Maximum number of mesh links. | 
| 19 | #define GFX_MAX_NUM_MESH_LINKS 1024 | 19 | #define GFX_MAX_NUM_MESH_LINKS 1024 | 
| 20 | 20 | ||
| 21 | /// Maximum number of models. | ||
| 22 | #define GFX_MAX_NUM_MODELS 64 | ||
| 23 | |||
| 21 | /// Maximum number of joints per skeleton. | 24 | /// Maximum number of joints per skeleton. | 
| 22 | #define GFX_MAX_NUM_JOINTS 96 | 25 | #define GFX_MAX_NUM_JOINTS 96 | 
| 23 | 26 | ||
| 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 @@ | |||
| 4 | #include "texture.h" | 4 | #include "texture.h" | 
| 5 | #include <gfx/asset.h> | 5 | #include <gfx/asset.h> | 
| 6 | #include <gfx/gfx.h> | 6 | #include <gfx/gfx.h> | 
| 7 | #include <gfx/scene/node.h> | ||
| 8 | #include <gfx_assert.h> | 7 | #include <gfx_assert.h> | 
| 9 | 8 | ||
| 10 | #include "scene/node_impl.h" | ||
| 11 | |||
| 12 | #include <cstring.h> | 9 | #include <cstring.h> | 
| 13 | #include <log/log.h> | 10 | #include <log/log.h> | 
| 14 | 11 | ||
| 15 | static Hash calc_scene_hash(const LoadSceneCmd* cmd) { | 12 | static Hash calc_model_hash(const LoadModelCmd* cmd) { | 
| 16 | assert(cmd); | 13 | assert(cmd); | 
| 17 | switch (cmd->origin) { | 14 | switch (cmd->origin) { | 
| 18 | case AssetFromFile: | 15 | case AssetFromFile: | 
| @@ -20,7 +17,7 @@ static Hash calc_scene_hash(const LoadSceneCmd* cmd) { | |||
| 20 | case AssetFromMemory: | 17 | case AssetFromMemory: | 
| 21 | return (Hash)cmd->data; | 18 | return (Hash)cmd->data; | 
| 22 | } | 19 | } | 
| 23 | FAIL("Unhandled scene asset origin"); | 20 | FAIL("Unhandled model asset origin"); | 
| 24 | return 0; | 21 | return 0; | 
| 25 | } | 22 | } | 
| 26 | 23 | ||
| @@ -74,7 +71,7 @@ static Asset* lookup_cache(AssetCache* cache, Hash hash) { | |||
| 74 | return 0; | 71 | return 0; | 
| 75 | } | 72 | } | 
| 76 | 73 | ||
| 77 | static void log_scene_cache_hit(const LoadSceneCmd* cmd, Hash hash) { | 74 | static void log_model_cache_hit(const LoadModelCmd* cmd, Hash hash) { | 
| 78 | assert(cmd); | 75 | assert(cmd); | 
| 79 | switch (cmd->origin) { | 76 | switch (cmd->origin) { | 
| 80 | case AssetFromFile: | 77 | case AssetFromFile: | 
| @@ -88,7 +85,7 @@ static void log_scene_cache_hit(const LoadSceneCmd* cmd, Hash hash) { | |||
| 88 | } | 85 | } | 
| 89 | } | 86 | } | 
| 90 | 87 | ||
| 91 | static void log_scene_loaded(const LoadSceneCmd* cmd) { | 88 | static void log_model_loaded(const LoadModelCmd* cmd) { | 
| 92 | assert(cmd); | 89 | assert(cmd); | 
| 93 | switch (cmd->origin) { | 90 | switch (cmd->origin) { | 
| 94 | case AssetFromFile: | 91 | case AssetFromFile: | 
| @@ -115,32 +112,31 @@ void gfx_destroy_asset_cache(AssetCache* cache) { | |||
| 115 | mempool_del(&cache->assets); | 112 | mempool_del(&cache->assets); | 
| 116 | } | 113 | } | 
| 117 | 114 | ||
| 118 | SceneNode* gfx_load_scene( | 115 | Model* gfx_load_model(Gfx* gfx, const LoadModelCmd* cmd) { | 
| 119 | Gfx* gfx, SceneNode* parent_node, const LoadSceneCmd* cmd) { | ||
| 120 | assert(gfx); | 116 | assert(gfx); | 
| 121 | 117 | ||
| 122 | AssetCache* cache = gfx_get_asset_cache(gfx); | 118 | AssetCache* cache = gfx_get_asset_cache(gfx); | 
| 123 | 119 | ||
| 124 | // First search for the asset in the cache. | 120 | // First search for the asset in the cache. | 
| 125 | const uint64_t hash = calc_scene_hash(cmd); | 121 | const uint64_t hash = calc_model_hash(cmd); | 
| 126 | Asset* asset = lookup_cache(cache, hash); | 122 | Asset* asset = lookup_cache(cache, hash); | 
| 127 | if (asset) { | 123 | if (asset) { | 
| 128 | log_scene_cache_hit(cmd, hash); | 124 | log_model_cache_hit(cmd, hash); | 
| 129 | return (SceneNode*)asset; | 125 | return asset->model; | 
| 130 | } | 126 | } | 
| 131 | 127 | ||
| 132 | // Asset not found in the cache. | 128 | // Asset not found in the cache. | 
| 133 | // Load it, insert it into the cache, and return it. | 129 | // Load it, insert it into the cache, and return it. | 
| 134 | SceneNode* node = gfx_scene_load(gfx, parent_node, cmd); | 130 | Model* model = gfx_model_load(gfx, cmd); | 
| 135 | if (node) { | 131 | if (model) { | 
| 136 | *(Asset*)mempool_alloc(&cache->assets) = (Asset){ | 132 | *(Asset*)mempool_alloc(&cache->assets) = (Asset){ | 
| 137 | .type = SceneAsset, | 133 | .type = ModelAsset, | 
| 138 | .hash = hash, | 134 | .hash = hash, | 
| 139 | .data = node, | 135 | .model = model, | 
| 140 | }; | 136 | }; | 
| 141 | log_scene_loaded(cmd); | 137 | log_model_loaded(cmd); | 
| 142 | } | 138 | } | 
| 143 | return node; | 139 | return model; | 
| 144 | } | 140 | } | 
| 145 | 141 | ||
| 146 | Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) { | 142 | Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) { | 
| @@ -153,7 +149,7 @@ Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) { | |||
| 153 | const uint64_t hash = calc_texture_hash(cmd); | 149 | const uint64_t hash = calc_texture_hash(cmd); | 
| 154 | Asset* asset = lookup_cache(cache, hash); | 150 | Asset* asset = lookup_cache(cache, hash); | 
| 155 | if (asset) { | 151 | if (asset) { | 
| 156 | return (Texture*)asset; | 152 | return asset->texture; | 
| 157 | } | 153 | } | 
| 158 | 154 | ||
| 159 | // Asset not found in the cache. | 155 | // Asset not found in the cache. | 
| @@ -162,9 +158,9 @@ Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) { | |||
| 162 | Texture* texture = gfx_texture_load(render_backend, cmd); | 158 | Texture* texture = gfx_texture_load(render_backend, cmd); | 
| 163 | if (texture) { | 159 | if (texture) { | 
| 164 | *(Asset*)mempool_alloc(&cache->assets) = (Asset){ | 160 | *(Asset*)mempool_alloc(&cache->assets) = (Asset){ | 
| 165 | .type = TextureAsset, | 161 | .type = TextureAsset, | 
| 166 | .hash = hash, | 162 | .hash = hash, | 
| 167 | .data = texture, | 163 | .texture = texture, | 
| 168 | }; | 164 | }; | 
| 169 | } | 165 | } | 
| 170 | return texture; | 166 | 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 @@ | |||
| 5 | #include <cstring.h> | 5 | #include <cstring.h> | 
| 6 | #include <mempool.h> | 6 | #include <mempool.h> | 
| 7 | 7 | ||
| 8 | typedef struct Model Model; | ||
| 9 | typedef struct Texture Texture; | ||
| 10 | |||
| 8 | typedef uint64_t Hash; | 11 | typedef uint64_t Hash; | 
| 9 | 12 | ||
| 10 | typedef enum AssetType { | 13 | typedef enum AssetType { | 
| 11 | SceneAsset, | 14 | ModelAsset, | 
| 12 | TextureAsset, | 15 | TextureAsset, | 
| 13 | } AssetType; | 16 | } AssetType; | 
| 14 | 17 | ||
| 15 | typedef struct Asset { | 18 | typedef struct Asset { | 
| 16 | AssetType type; | 19 | AssetType type; | 
| 17 | Hash hash; | 20 | Hash hash; | 
| 18 | void* data; | 21 | union { | 
| 22 | Model* model; | ||
| 23 | Texture* texture; | ||
| 24 | }; | ||
| 19 | } Asset; | 25 | } Asset; | 
| 20 | 26 | ||
| 21 | DEF_MEMPOOL(asset_pool, Asset, GFX_MAX_NUM_ASSETS) | 27 | 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 @@ | |||
| 94 | #include "gfx/sizes.h" | 94 | #include "gfx/sizes.h" | 
| 95 | #include "gfx/util/shader.h" | 95 | #include "gfx/util/shader.h" | 
| 96 | 96 | ||
| 97 | #include "scene/model_impl.h" | ||
| 98 | |||
| 97 | #include "cstring.h" | 99 | #include "cstring.h" | 
| 98 | #include "error.h" | 100 | #include "error.h" | 
| 99 | #include "log/log.h" | 101 | #include "log/log.h" | 
| @@ -1487,16 +1489,16 @@ static void load_nodes( | |||
| 1487 | } // SceneNode. | 1489 | } // SceneNode. | 
| 1488 | } | 1490 | } | 
| 1489 | 1491 | ||
| 1490 | /// Load all scenes from the glTF file into the given gfx Scene. | 1492 | /// Load all scenes from the glTF file. | 
| 1491 | /// | 1493 | /// | 
| 1492 | /// If the scene is loaded from memory, set filepath = null. | 1494 | /// If the scene is loaded from memory, set filepath = null. | 
| 1493 | /// | 1495 | /// | 
| 1494 | /// This function ignores the many scenes and default scene of the glTF spec | 1496 | /// This function ignores the many scenes and default scene of the glTF spec | 
| 1495 | /// and instead just loads all scenes into a single gfx Scene. | 1497 | /// and instead just loads all scenes into a single Gfx Scene. | 
| 1496 | static SceneNode* load_scene( | 1498 | static Model* load_scene( | 
| 1497 | cgltf_data* data, Gfx* gfx, SceneNode* parent_node, const mstring* filepath, | 1499 | cgltf_data* data, Gfx* gfx, const mstring* filepath, ShaderProgram* shader, | 
| 1498 | ShaderProgram* shader, const cgltfTangentBuffer* cgltf_tangent_buffers, | 1500 | const cgltfTangentBuffer* cgltf_tangent_buffers, | 
| 1499 | cgltf_size num_tangent_buffers) { | 1501 | cgltf_size num_tangent_buffers) { | 
| 1500 | // In a GLTF scene, buffers can be shared among meshes, meshes among nodes, | 1502 | // In a GLTF scene, buffers can be shared among meshes, meshes among nodes, | 
| 1501 | // etc. Each object is referenced by its index in the relevant array. Here we | 1503 | // etc. Each object is referenced by its index in the relevant array. Here we | 
| 1502 | // do a button-up construction, first allocating our own graphics objects in | 1504 | // do a button-up construction, first allocating our own graphics objects in | 
| @@ -1540,6 +1542,7 @@ static SceneNode* load_scene( | |||
| 1540 | SceneNode** scene_nodes = 0; | 1542 | SceneNode** scene_nodes = 0; | 
| 1541 | Anima* anima = 0; | 1543 | Anima* anima = 0; | 
| 1542 | SceneNode* root_node = 0; | 1544 | SceneNode* root_node = 0; | 
| 1545 | Model* model = 0; | ||
| 1543 | 1546 | ||
| 1544 | tangent_buffers = calloc(num_tangent_buffers, sizeof(Buffer*)); | 1547 | tangent_buffers = calloc(num_tangent_buffers, sizeof(Buffer*)); | 
| 1545 | buffers = calloc(data->buffers_count, sizeof(Buffer*)); | 1548 | buffers = calloc(data->buffers_count, sizeof(Buffer*)); | 
| @@ -1619,13 +1622,14 @@ static SceneNode* load_scene( | |||
| 1619 | anima = gfx_make_anima(anima_desc); | 1622 | anima = gfx_make_anima(anima_desc); | 
| 1620 | gfx_construct_anima_node(root_node, anima); | 1623 | gfx_construct_anima_node(root_node, anima); | 
| 1621 | } | 1624 | } | 
| 1622 | gfx_set_node_parent(root_node, parent_node); | ||
| 1623 | 1625 | ||
| 1624 | // The root node becomes the root of all scene nodes. | 1626 | // The root node becomes the root of all scene nodes. | 
| 1625 | load_nodes(data, root_node, scene_objects, scene_cameras, anima, scene_nodes); | 1627 | load_nodes(data, root_node, scene_objects, scene_cameras, anima, scene_nodes); | 
| 1626 | 1628 | ||
| 1627 | // TODO: Clean up scene nodes that correspond to joints in the glTF. | 1629 | // TODO: Clean up scene nodes that correspond to joints in the glTF. | 
| 1628 | 1630 | ||
| 1631 | model = gfx_make_model(root_node); | ||
| 1632 | |||
| 1629 | success = true; | 1633 | success = true; | 
| 1630 | 1634 | ||
| 1631 | cleanup: | 1635 | cleanup: | 
| @@ -1734,16 +1738,14 @@ cleanup: | |||
| 1734 | gfx_destroy_anima(&anima); | 1738 | gfx_destroy_anima(&anima); | 
| 1735 | } | 1739 | } | 
| 1736 | } | 1740 | } | 
| 1737 | return root_node; | 1741 | return model; | 
| 1738 | } | 1742 | } | 
| 1739 | 1743 | ||
| 1740 | SceneNode* gfx_scene_load( | 1744 | Model* gfx_model_load(Gfx* gfx, const LoadModelCmd* cmd) { | 
| 1741 | Gfx* gfx, SceneNode* parent_node, const LoadSceneCmd* cmd) { | ||
| 1742 | assert(gfx); | 1745 | assert(gfx); | 
| 1743 | assert(parent_node); | ||
| 1744 | assert(cmd); | 1746 | assert(cmd); | 
| 1745 | 1747 | ||
| 1746 | SceneNode* scene_node = 0; | 1748 | Model* model = 0; | 
| 1747 | 1749 | ||
| 1748 | cgltf_options options = {0}; | 1750 | cgltf_options options = {0}; | 
| 1749 | cgltf_data* data = NULL; | 1751 | cgltf_data* data = NULL; | 
| @@ -1775,8 +1777,8 @@ SceneNode* gfx_scene_load( | |||
| 1775 | cgltf_compute_tangents( | 1777 | cgltf_compute_tangents( | 
| 1776 | &options, data, &tangent_buffers, &num_tangent_buffers); | 1778 | &options, data, &tangent_buffers, &num_tangent_buffers); | 
| 1777 | 1779 | ||
| 1778 | scene_node = load_scene( | 1780 | model = load_scene( | 
| 1779 | data, gfx, parent_node, &cmd->filepath, cmd->shader, tangent_buffers, | 1781 | data, gfx, &cmd->filepath, cmd->shader, tangent_buffers, | 
| 1780 | num_tangent_buffers); | 1782 | num_tangent_buffers); | 
| 1781 | 1783 | ||
| 1782 | cleanup: | 1784 | cleanup: | 
| @@ -1786,5 +1788,5 @@ cleanup: | |||
| 1786 | if (tangent_buffers) { | 1788 | if (tangent_buffers) { | 
| 1787 | free(tangent_buffers); | 1789 | free(tangent_buffers); | 
| 1788 | } | 1790 | } | 
| 1789 | return scene_node; | 1791 | return model; | 
| 1790 | } | 1792 | } | 
| 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 @@ | |||
| 3 | 3 | ||
| 4 | #include <gfx/asset.h> | 4 | #include <gfx/asset.h> | 
| 5 | 5 | ||
| 6 | typedef struct Gfx Gfx; | 6 | typedef struct Gfx Gfx; | 
| 7 | typedef struct SceneNode SceneNode; | 7 | typedef struct Model Model; | 
| 8 | 8 | ||
| 9 | /// Load a scene. | 9 | /// Load a model. | 
| 10 | /// | ||
| 11 | /// Return the top-level node under which scene elements are rooted. | ||
| 12 | /// | ||
| 13 | /// |parent_node| is made the parent of the returned top-level node. It may be | ||
| 14 | /// null. | ||
| 15 | /// | 10 | /// | 
| 16 | /// Currently only supports the GLTF format. | 11 | /// Currently only supports the GLTF format. | 
| 17 | SceneNode* gfx_scene_load(Gfx*, SceneNode* parent_node, const LoadSceneCmd*); | 12 | 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 @@ | |||
| 1 | #include "renderer_impl.h" | 1 | #include "renderer_impl.h" | 
| 2 | 2 | ||
| 3 | #include "scene/animation_impl.h" | ||
| 3 | #include "scene/camera_impl.h" | 4 | #include "scene/camera_impl.h" | 
| 4 | #include "scene/light_impl.h" | 5 | #include "scene/light_impl.h" | 
| 5 | #include "scene/material_impl.h" | 6 | #include "scene/material_impl.h" | 
| 6 | #include "scene/mesh_impl.h" | 7 | #include "scene/mesh_impl.h" | 
| 8 | #include "scene/model_impl.h" | ||
| 7 | #include "scene/node_impl.h" | 9 | #include "scene/node_impl.h" | 
| 8 | #include "scene/object_impl.h" | 10 | #include "scene/object_impl.h" | 
| 9 | #include "scene/scene_impl.h" | 11 | #include "scene/scene_impl.h" | 
| @@ -207,10 +209,12 @@ static void draw_recursively( | |||
| 207 | assert(state); | 209 | assert(state); | 
| 208 | const mat4 node_transform = mat4_mul(parent_transform, node->transform); | 210 | const mat4 node_transform = mat4_mul(parent_transform, node->transform); | 
| 209 | 211 | ||
| 210 | // Activate light. | 212 | // Anima. | 
| 211 | if (node->type == AnimaNode) { | 213 | if (node->type == AnimaNode) { | 
| 212 | state->anima = gfx_get_node_anima(node); | 214 | state->anima = gfx_get_node_anima(node); | 
| 213 | } else if (node->type == LightNode) { | 215 | } | 
| 216 | // Activate light. | ||
| 217 | else if (node->type == LightNode) { | ||
| 214 | Light* light = mem_get_light(node->light); | 218 | Light* light = mem_get_light(node->light); | 
| 215 | assert(light); | 219 | assert(light); | 
| 216 | 220 | ||
| @@ -222,6 +226,12 @@ static void draw_recursively( | |||
| 222 | state->environment_light = light; | 226 | state->environment_light = light; | 
| 223 | } | 227 | } | 
| 224 | } | 228 | } | 
| 229 | // Model. | ||
| 230 | else if (node->type == ModelNode) { | ||
| 231 | const Model* model = gfx_get_node_model(node); | ||
| 232 | const SceneNode* root = mem_get_node(model->root); | ||
| 233 | draw_recursively(state, parent_transform, root); | ||
| 234 | } | ||
| 225 | // Render object. | 235 | // Render object. | 
| 226 | else if (node->type == ObjectNode) { | 236 | else if (node->type == ObjectNode) { | 
| 227 | const SceneObject* object = mem_get_object(node->object); | 237 | 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 @@ | |||
| 1 | #include "model_impl.h" | ||
| 2 | |||
| 3 | #include <gfx/scene/node.h> | ||
| 4 | |||
| 5 | #include "scene_memory.h" | ||
| 6 | |||
| 7 | #include <assert.h> | ||
| 8 | |||
| 9 | Model* gfx_make_model(const SceneNode* root) { | ||
| 10 | assert(root); | ||
| 11 | |||
| 12 | Model* model = mem_alloc_model(); | ||
| 13 | model->root = mem_get_node_index(root); | ||
| 14 | return model; | ||
| 15 | } | ||
| 16 | |||
| 17 | void gfx_del_model(Model** model) { | ||
| 18 | assert(model); | ||
| 19 | |||
| 20 | if (*model) { | ||
| 21 | SceneNode* root = mem_get_node((*model)->root); | ||
| 22 | gfx_destroy_node(&root); | ||
| 23 | *model = 0; | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | Anima* gfx_get_model_anima(Model* model) { | ||
| 28 | assert(model); | ||
| 29 | |||
| 30 | SceneNode* root = mem_get_node(model->root); | ||
| 31 | if (gfx_get_node_type(root) == AnimaNode) { | ||
| 32 | return gfx_get_node_anima(root); | ||
| 33 | } else { | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | const SceneNode* gfx_get_model_root(const Model* model) { | ||
| 39 | assert(model); | ||
| 40 | return mem_get_node(model->root); | ||
| 41 | } | ||
| 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 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <gfx/scene/model.h> | ||
| 4 | |||
| 5 | #include "scene_memory.h" | ||
| 6 | |||
| 7 | /// Model. | ||
| 8 | typedef struct Model { | ||
| 9 | node_idx root; | ||
| 10 | node_idx parent; // Parent SceneNode. | ||
| 11 | } Model; | ||
| 12 | |||
| 13 | /// Create a new model. | ||
| 14 | Model* gfx_make_model(const SceneNode* root); | ||
| 15 | |||
| 16 | /// Destroy the model. | ||
| 17 | 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 @@ | |||
| 1 | #include "node_impl.h" | 1 | #include "node_impl.h" | 
| 2 | 2 | ||
| 3 | #include "animation_impl.h" | ||
| 3 | #include "camera_impl.h" | 4 | #include "camera_impl.h" | 
| 4 | #include "light_impl.h" | 5 | #include "light_impl.h" | 
| 6 | #include "model_impl.h" | ||
| 5 | #include "object_impl.h" | 7 | #include "object_impl.h" | 
| 6 | #include "scene_graph.h" | 8 | #include "scene_graph.h" | 
| 7 | #include "scene_memory.h" | 9 | #include "scene_memory.h" | 
| 8 | 10 | ||
| 11 | #include "gfx_assert.h" | ||
| 12 | |||
| 9 | #include <cstring.h> | 13 | #include <cstring.h> | 
| 10 | #include <log/log.h> | 14 | #include <log/log.h> | 
| 11 | 15 | ||
| 12 | #include <assert.h> | ||
| 13 | |||
| 14 | static void scene_node_make(SceneNode* node) { | 16 | static void scene_node_make(SceneNode* node) { | 
| 15 | assert(node); | 17 | assert(node); | 
| 16 | node->type = LogicalNode; | 18 | node->type = LogicalNode; | 
| @@ -50,6 +52,15 @@ SceneNode* gfx_make_light_node(Light* light) { | |||
| 50 | return node; | 52 | return node; | 
| 51 | } | 53 | } | 
| 52 | 54 | ||
| 55 | SceneNode* gfx_make_model_node(Model* model) { | ||
| 56 | assert(model); | ||
| 57 | SceneNode* node = gfx_make_node(); | ||
| 58 | node->type = ModelNode; | ||
| 59 | node->model = mem_get_model_index(model); | ||
| 60 | model->parent = mem_get_node_index(node); | ||
| 61 | return node; | ||
| 62 | } | ||
| 63 | |||
| 53 | SceneNode* gfx_make_object_node(SceneObject* object) { | 64 | SceneNode* gfx_make_object_node(SceneObject* object) { | 
| 54 | assert(object); | 65 | assert(object); | 
| 55 | SceneNode* node = gfx_make_node(); | 66 | SceneNode* node = gfx_make_node(); | 
| @@ -70,29 +81,33 @@ static void free_node_resource(SceneNode* node) { | |||
| 70 | Anima* anima = mem_get_anima(node->anima); | 81 | Anima* anima = mem_get_anima(node->anima); | 
| 71 | anima->parent.val = 0; | 82 | anima->parent.val = 0; | 
| 72 | gfx_destroy_anima(&anima); | 83 | gfx_destroy_anima(&anima); | 
| 73 | break; | 84 | return; | 
| 74 | } | 85 | } | 
| 75 | case CameraNode: { | 86 | case CameraNode: { | 
| 76 | SceneCamera* camera = mem_get_camera(node->camera); | 87 | SceneCamera* camera = mem_get_camera(node->camera); | 
| 77 | camera->parent.val = 0; | 88 | camera->parent.val = 0; | 
| 78 | gfx_destroy_camera(&camera); | 89 | gfx_destroy_camera(&camera); | 
| 79 | break; | 90 | return; | 
| 80 | } | 91 | } | 
| 81 | case LightNode: { | 92 | case LightNode: { | 
| 82 | Light* light = mem_get_light(node->light); | 93 | Light* light = mem_get_light(node->light); | 
| 83 | light->parent.val = 0; | 94 | light->parent.val = 0; | 
| 84 | gfx_destroy_light(&light); | 95 | gfx_destroy_light(&light); | 
| 85 | break; | 96 | return; | 
| 97 | } | ||
| 98 | case ModelNode: { | ||
| 99 | return; // Model data is owned by the asset cache. | ||
| 86 | } | 100 | } | 
| 87 | case ObjectNode: { | 101 | case ObjectNode: { | 
| 88 | SceneObject* object = mem_get_object(node->object); | 102 | SceneObject* object = mem_get_object(node->object); | 
| 89 | object->parent.val = 0; | 103 | object->parent.val = 0; | 
| 90 | gfx_destroy_object(&object); | 104 | gfx_destroy_object(&object); | 
| 91 | break; | 105 | return; | 
| 92 | } | 106 | } | 
| 93 | case LogicalNode: | 107 | case LogicalNode: | 
| 94 | break; // Logical nodes have no resource. | 108 | return; // Logical nodes have no resource. | 
| 95 | } | 109 | } | 
| 110 | FAIL("unhandled node type"); | ||
| 96 | } | 111 | } | 
| 97 | 112 | ||
| 98 | void gfx_construct_anima_node(SceneNode* node, Anima* anima) { | 113 | void gfx_construct_anima_node(SceneNode* node, Anima* anima) { | 
| @@ -124,6 +139,15 @@ void gfx_construct_light_node(SceneNode* node, Light* light) { | |||
| 124 | light->parent = mem_get_node_index(node); | 139 | light->parent = mem_get_node_index(node); | 
| 125 | } | 140 | } | 
| 126 | 141 | ||
| 142 | void gfx_construct_model_node(SceneNode* node, Model* model) { | ||
| 143 | assert(node); | ||
| 144 | assert(model); | ||
| 145 | free_node_resource(node); | ||
| 146 | node->type = ModelNode; | ||
| 147 | node->model = mem_get_model_index(model); | ||
| 148 | model->parent = mem_get_node_index(node); | ||
| 149 | } | ||
| 150 | |||
| 127 | void gfx_construct_object_node(SceneNode* node, SceneObject* object) { | 151 | void gfx_construct_object_node(SceneNode* node, SceneObject* object) { | 
| 128 | assert(node); | 152 | assert(node); | 
| 129 | assert(object); | 153 | assert(object); | 
| @@ -197,6 +221,10 @@ Light* gfx_get_node_light(const SceneNode* node) { | |||
| 197 | NODE_GET(node, light, LightNode); | 221 | NODE_GET(node, light, LightNode); | 
| 198 | } | 222 | } | 
| 199 | 223 | ||
| 224 | Model* gfx_get_node_model(const SceneNode* node) { | ||
| 225 | NODE_GET(node, model, ModelNode); | ||
| 226 | } | ||
| 227 | |||
| 200 | SceneObject* gfx_get_node_object(const SceneNode* node) { | 228 | SceneObject* gfx_get_node_object(const SceneNode* node) { | 
| 201 | NODE_GET(node, object, ObjectNode); | 229 | NODE_GET(node, object, ObjectNode); | 
| 202 | } | 230 | } | 
| @@ -283,10 +311,12 @@ static const char* get_node_type_str(NodeType type) { | |||
| 283 | return "CameraNode"; | 311 | return "CameraNode"; | 
| 284 | case LightNode: | 312 | case LightNode: | 
| 285 | return "LightNode"; | 313 | return "LightNode"; | 
| 314 | case ModelNode: | ||
| 315 | return "ModelNode"; | ||
| 286 | case ObjectNode: | 316 | case ObjectNode: | 
| 287 | return "ObjectNode"; | 317 | return "ObjectNode"; | 
| 288 | } | 318 | } | 
| 289 | assert(false); | 319 | FAIL("Unhandled node type"); | 
| 290 | return ""; | 320 | return ""; | 
| 291 | } | 321 | } | 
| 292 | 322 | ||
| 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 { | |||
| 17 | anima_idx anima; | 17 | anima_idx anima; | 
| 18 | camera_idx camera; | 18 | camera_idx camera; | 
| 19 | light_idx light; | 19 | light_idx light; | 
| 20 | model_idx model; | ||
| 20 | object_idx object; | 21 | object_idx object; | 
| 21 | }; | 22 | }; | 
| 22 | mat4 transform; // Transformation for this node and its children. | 23 | 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) { | |||
| 23 | assert(scene); | 23 | assert(scene); | 
| 24 | return scene->root; | 24 | return scene->root; | 
| 25 | } | 25 | } | 
| 26 | |||
| 27 | static void gfx_animate_node(SceneNode* node, R t) { | ||
| 28 | assert(node); | ||
| 29 | |||
| 30 | if (gfx_get_node_type(node) == AnimaNode) { | ||
| 31 | gfx_update_animation(gfx_get_node_anima(node), t); | ||
| 32 | } | ||
| 33 | |||
| 34 | for (NodeIter it = gfx_get_node_child(node); it; | ||
| 35 | it = gfx_get_next_child(it)) { | ||
| 36 | gfx_animate_node(gfx_get_iter_node_mut(it), t); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | void gfx_animate_scene(Scene* scene, R t) { | ||
| 41 | assert(scene); | ||
| 42 | SceneNode* node = gfx_get_scene_root(scene); | ||
| 43 | gfx_animate_node(node, t); | ||
| 44 | } | ||
| 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 @@ | |||
| 7 | #include "light_impl.h" | 7 | #include "light_impl.h" | 
| 8 | #include "material_impl.h" | 8 | #include "material_impl.h" | 
| 9 | #include "mesh_impl.h" | 9 | #include "mesh_impl.h" | 
| 10 | #include "model_impl.h" | ||
| 10 | #include "node_impl.h" | 11 | #include "node_impl.h" | 
| 11 | #include "object_impl.h" | 12 | #include "object_impl.h" | 
| 12 | #include "scene_impl.h" | 13 | #include "scene_impl.h" | 
| @@ -20,6 +21,7 @@ DEF_MEMPOOL(light_pool, Light, GFX_MAX_NUM_LIGHTS) | |||
| 20 | DEF_MEMPOOL(material_pool, Material, GFX_MAX_NUM_MATERIALS) | 21 | DEF_MEMPOOL(material_pool, Material, GFX_MAX_NUM_MATERIALS) | 
| 21 | DEF_MEMPOOL(mesh_pool, Mesh, GFX_MAX_NUM_MESHES) | 22 | DEF_MEMPOOL(mesh_pool, Mesh, GFX_MAX_NUM_MESHES) | 
| 22 | DEF_MEMPOOL(mesh_link_pool, MeshLink, GFX_MAX_NUM_MESH_LINKS) | 23 | DEF_MEMPOOL(mesh_link_pool, MeshLink, GFX_MAX_NUM_MESH_LINKS) | 
| 24 | DEF_MEMPOOL(model_pool, Model, GFX_MAX_NUM_MODELS) | ||
| 23 | DEF_MEMPOOL(node_pool, SceneNode, GFX_MAX_NUM_NODES) | 25 | DEF_MEMPOOL(node_pool, SceneNode, GFX_MAX_NUM_NODES) | 
| 24 | DEF_MEMPOOL(object_pool, SceneObject, GFX_MAX_NUM_OBJECTS) | 26 | DEF_MEMPOOL(object_pool, SceneObject, GFX_MAX_NUM_OBJECTS) | 
| 25 | DEF_MEMPOOL(scene_pool, Scene, GFX_MAX_NUM_SCENES) | 27 | DEF_MEMPOOL(scene_pool, Scene, GFX_MAX_NUM_SCENES) | 
| @@ -36,6 +38,7 @@ typedef struct SceneMemory { | |||
| 36 | material_pool materials; | 38 | material_pool materials; | 
| 37 | mesh_pool meshs; // Purposeful typo to make the PLURAL() macro work. | 39 | mesh_pool meshs; // Purposeful typo to make the PLURAL() macro work. | 
| 38 | mesh_link_pool mesh_links; | 40 | mesh_link_pool mesh_links; | 
| 41 | model_pool models; | ||
| 39 | node_pool nodes; | 42 | node_pool nodes; | 
| 40 | object_pool objects; | 43 | object_pool objects; | 
| 41 | scene_pool scenes; | 44 | scene_pool scenes; | 
| @@ -61,6 +64,7 @@ void scene_mem_init() { | |||
| 61 | mempool_make(&mem.materials); | 64 | mempool_make(&mem.materials); | 
| 62 | mempool_make(&mem.meshs); | 65 | mempool_make(&mem.meshs); | 
| 63 | mempool_make(&mem.mesh_links); | 66 | mempool_make(&mem.mesh_links); | 
| 67 | mempool_make(&mem.models); | ||
| 64 | mempool_make(&mem.nodes); | 68 | mempool_make(&mem.nodes); | 
| 65 | mempool_make(&mem.objects); | 69 | mempool_make(&mem.objects); | 
| 66 | mempool_make(&mem.scenes); | 70 | mempool_make(&mem.scenes); | 
| @@ -75,6 +79,7 @@ void scene_mem_init() { | |||
| 75 | ALLOC_DUMMY(&mem.materials); | 79 | ALLOC_DUMMY(&mem.materials); | 
| 76 | ALLOC_DUMMY(&mem.meshs); | 80 | ALLOC_DUMMY(&mem.meshs); | 
| 77 | ALLOC_DUMMY(&mem.mesh_links); | 81 | ALLOC_DUMMY(&mem.mesh_links); | 
| 82 | ALLOC_DUMMY(&mem.models); | ||
| 78 | ALLOC_DUMMY(&mem.nodes); | 83 | ALLOC_DUMMY(&mem.nodes); | 
| 79 | ALLOC_DUMMY(&mem.objects); | 84 | ALLOC_DUMMY(&mem.objects); | 
| 80 | ALLOC_DUMMY(&mem.scenes); | 85 | ALLOC_DUMMY(&mem.scenes); | 
| @@ -92,6 +97,9 @@ void scene_mem_destroy() { | |||
| 92 | } \ | 97 | } \ | 
| 93 | }) | 98 | }) | 
| 94 | 99 | ||
| 100 | // Models contain scene elements. Destruction is handled by the remainder of | ||
| 101 | // scene destructionb elow. | ||
| 102 | // | ||
| 95 | // First destroy the scenes. This will recursively destroy the scene's nodes | 103 | // First destroy the scenes. This will recursively destroy the scene's nodes | 
| 96 | // and their objects and avoid a double-free when we then destroy any stray | 104 | // and their objects and avoid a double-free when we then destroy any stray | 
| 97 | // scene elements. | 105 | // scene elements. | 
| @@ -135,6 +143,7 @@ DEF_MEMORY(light, Light) | |||
| 135 | DEF_MEMORY(material, Material) | 143 | DEF_MEMORY(material, Material) | 
| 136 | DEF_MEMORY(mesh, Mesh) | 144 | DEF_MEMORY(mesh, Mesh) | 
| 137 | DEF_MEMORY(mesh_link, MeshLink) | 145 | DEF_MEMORY(mesh_link, MeshLink) | 
| 146 | DEF_MEMORY(model, Model) | ||
| 138 | DEF_MEMORY(node, SceneNode) | 147 | DEF_MEMORY(node, SceneNode) | 
| 139 | DEF_MEMORY(object, SceneObject) | 148 | DEF_MEMORY(object, SceneObject) | 
| 140 | DEF_MEMORY(scene, Scene) | 149 | 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 @@ | |||
| 1 | /// Memory management of scene objects. | 1 | /// Memory management of scene objects. | 
| 2 | #pragma once | 2 | #pragma once | 
| 3 | 3 | ||
| 4 | #include "animation_impl.h" | ||
| 5 | #include "types.h" | 4 | #include "types.h" | 
| 6 | 5 | ||
| 7 | /// Initialize scene memory. | 6 | /// Initialize scene memory. | 
| @@ -33,6 +32,7 @@ DECL_MEMORY(light, Light) | |||
| 33 | DECL_MEMORY(material, Material) | 32 | DECL_MEMORY(material, Material) | 
| 34 | DECL_MEMORY(mesh, Mesh) | 33 | DECL_MEMORY(mesh, Mesh) | 
| 35 | DECL_MEMORY(mesh_link, MeshLink) | 34 | DECL_MEMORY(mesh_link, MeshLink) | 
| 35 | DECL_MEMORY(model, Model) | ||
| 36 | DECL_MEMORY(node, SceneNode) | 36 | DECL_MEMORY(node, SceneNode) | 
| 37 | DECL_MEMORY(object, SceneObject) | 37 | DECL_MEMORY(object, SceneObject) | 
| 38 | DECL_MEMORY(scene, Scene) | 38 | 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) | |||
| 18 | DEF_STRONG_INDEX(material, gfx_idx) | 18 | DEF_STRONG_INDEX(material, gfx_idx) | 
| 19 | DEF_STRONG_INDEX(mesh, gfx_idx) | 19 | DEF_STRONG_INDEX(mesh, gfx_idx) | 
| 20 | DEF_STRONG_INDEX(mesh_link, gfx_idx) | 20 | DEF_STRONG_INDEX(mesh_link, gfx_idx) | 
| 21 | DEF_STRONG_INDEX(model, gfx_idx) | ||
| 21 | DEF_STRONG_INDEX(node, gfx_idx) | 22 | DEF_STRONG_INDEX(node, gfx_idx) | 
| 22 | DEF_STRONG_INDEX(object, gfx_idx) | 23 | DEF_STRONG_INDEX(object, gfx_idx) | 
| 23 | DEF_STRONG_INDEX(scene, gfx_idx) | 24 | DEF_STRONG_INDEX(scene, gfx_idx) | 
