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