diff options
author | 3gg <3gg@shellblade.net> | 2024-02-12 17:42:57 -0800 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2024-02-12 17:42:57 -0800 |
commit | c593c24b62b274fbc1d465f0386a0c5d32423f4f (patch) | |
tree | d115b0255a491ab3562c8f79176454b45505be0a | |
parent | ef55b40db3cd5cb77f7c017df48fbbcbf07d58d3 (diff) |
Initial implementation for an asset cache.
-rw-r--r-- | game/src/plugins/viewer.c | 69 | ||||
-rw-r--r-- | gfx/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gfx/include/gfx/asset.h | 98 | ||||
-rw-r--r-- | gfx/include/gfx/gfx.h | 6 | ||||
-rw-r--r-- | gfx/include/gfx/sizes.h | 4 | ||||
-rw-r--r-- | gfx/include/gfx/util/scene.h | 24 | ||||
-rw-r--r-- | gfx/include/gfx/util/texture.h | 62 | ||||
-rw-r--r-- | gfx/src/asset/asset_cache.c | 183 | ||||
-rw-r--r-- | gfx/src/asset/asset_cache.h | 31 | ||||
-rw-r--r-- | gfx/src/gfx.c | 10 | ||||
-rw-r--r-- | gfx/src/util/scene.c | 74 | ||||
-rw-r--r-- | gfx/src/util/texture.c | 8 |
12 files changed, 419 insertions, 151 deletions
diff --git a/game/src/plugins/viewer.c b/game/src/plugins/viewer.c index 83fc8ed..1ed3b9d 100644 --- a/game/src/plugins/viewer.c +++ b/game/src/plugins/viewer.c | |||
@@ -30,31 +30,33 @@ struct State { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | /// Load the skyquad texture. | 32 | /// Load the skyquad texture. |
33 | static Texture* load_environment_map(RenderBackend* render_backend) { | 33 | static Texture* load_environment_map(Gfx* gfx) { |
34 | assert(gfx); | ||
34 | return gfx_load_texture( | 35 | return gfx_load_texture( |
35 | render_backend, | 36 | gfx, &(LoadTextureCmd){ |
36 | &(LoadTextureCmd){ | 37 | .origin = AssetFromFile, |
37 | .origin = TextureFromFile, | 38 | .type = LoadCubemap, |
38 | .type = LoadCubemap, | 39 | .colour_space = sRGB, |
39 | .colour_space = sRGB, | 40 | .filtering = NearestFiltering, |
40 | .filtering = NearestFiltering, | 41 | .mipmaps = false, |
41 | .mipmaps = false, | 42 | .data.cubemap.filepaths = { |
42 | .data.cubemap.filepaths = { | 43 | mstring_make("/assets/skybox/clouds1/clouds1_east.bmp"), |
43 | mstring_make("/assets/skybox/clouds1/clouds1_east.bmp"), | 44 | mstring_make("/assets/skybox/clouds1/clouds1_west.bmp"), |
44 | mstring_make("/assets/skybox/clouds1/clouds1_west.bmp"), | 45 | mstring_make("/assets/skybox/clouds1/clouds1_up.bmp"), |
45 | mstring_make("/assets/skybox/clouds1/clouds1_up.bmp"), | 46 | mstring_make("/assets/skybox/clouds1/clouds1_down.bmp"), |
46 | mstring_make("/assets/skybox/clouds1/clouds1_down.bmp"), | 47 | mstring_make("/assets/skybox/clouds1/clouds1_south.bmp"), |
47 | mstring_make("/assets/skybox/clouds1/clouds1_south.bmp"), | 48 | mstring_make("/assets/skybox/clouds1/clouds1_north.bmp")} |
48 | mstring_make("/assets/skybox/clouds1/clouds1_north.bmp")} | ||
49 | }); | 49 | }); |
50 | } | 50 | } |
51 | 51 | ||
52 | /// Load the skyquad and return the environment light node. | 52 | /// Load the skyquad and return the environment light node. |
53 | static SceneNode* load_skyquad(RenderBackend* render_backend, SceneNode* root) { | 53 | static SceneNode* load_skyquad(Gfx* gfx, SceneNode* root) { |
54 | assert(render_backend); | 54 | assert(gfx); |
55 | assert(root); | 55 | assert(root); |
56 | 56 | ||
57 | Texture* environment_map = load_environment_map(render_backend); | 57 | RenderBackend* render_backend = gfx_get_render_backend(gfx); |
58 | |||
59 | Texture* environment_map = load_environment_map(gfx); | ||
58 | if (!environment_map) { | 60 | if (!environment_map) { |
59 | return 0; | 61 | return 0; |
60 | } | 62 | } |
@@ -70,20 +72,19 @@ static SceneNode* load_scene( | |||
70 | assert(state); | 72 | assert(state); |
71 | assert(state->scene); | 73 | assert(state->scene); |
72 | 74 | ||
73 | SceneNode* root = gfx_get_scene_root(state->scene); | ||
74 | RenderBackend* render_backend = gfx_get_render_backend(game->gfx); | ||
75 | |||
76 | Camera* camera = gfx_get_camera_camera(state->camera); | 75 | Camera* camera = gfx_get_camera_camera(state->camera); |
77 | spatial3_set_position(&camera->spatial, vec3_make(0, 0, 2)); | 76 | spatial3_set_position(&camera->spatial, vec3_make(0, 0, 2)); |
78 | 77 | ||
79 | SceneNode* sky_light_node = load_skyquad(render_backend, root); | 78 | SceneNode* root = gfx_get_scene_root(state->scene); |
79 | SceneNode* sky_light_node = load_skyquad(game->gfx, root); | ||
80 | if (!sky_light_node) { | 80 | if (!sky_light_node) { |
81 | return 0; | 81 | return 0; // test |
82 | } | 82 | } |
83 | 83 | ||
84 | SceneNode* scene_node = gfx_load_scene( | 84 | SceneNode* scene_node = gfx_load_scene( |
85 | game->gfx, sky_light_node, | 85 | game->gfx, sky_light_node, |
86 | &(LoadSceneCmd){.origin = SceneFromFile, .filepath = scene_filepath}); | 86 | &(LoadSceneCmd){ |
87 | .origin = AssetFromFile, .filepath = mstring_make(scene_filepath)}); | ||
87 | if (!scene_node) { | 88 | if (!scene_node) { |
88 | return 0; | 89 | return 0; |
89 | } | 90 | } |
@@ -136,6 +137,10 @@ cleanup: | |||
136 | void shutdown(Game* game, State* state) { | 137 | void shutdown(Game* game, State* state) { |
137 | assert(game); | 138 | assert(game); |
138 | if (state) { | 139 | if (state) { |
140 | // TODO: Destroying the scene here currently does not play well with asset | ||
141 | // reloading. The issue is that we expect to mutate the scene/model during | ||
142 | // animation. This needs to change if we want to be able to cache assets | ||
143 | // in memory. | ||
139 | gfx_destroy_camera(&state->camera); | 144 | gfx_destroy_camera(&state->camera); |
140 | gfx_destroy_scene(&state->scene); | 145 | gfx_destroy_scene(&state->scene); |
141 | // State freed by plugin engine. | 146 | // State freed by plugin engine. |
@@ -165,8 +170,20 @@ static void render_bounding_boxes_rec(ImmRenderer* imm, const SceneNode* node) { | |||
165 | assert(node); | 170 | assert(node); |
166 | if (gfx_get_node_type(node) == ObjectNode) { | 171 | if (gfx_get_node_type(node) == ObjectNode) { |
167 | // TODO: Look at the scene log. The JointNodes are detached from the | 172 | // TODO: Look at the scene log. The JointNodes are detached from the |
168 | // ObjectNodes. This is why the boxes are not being transformed as expected | 173 | // ObjectNodes. This is why the boxes are not being transformed as expected |
169 | // here. Anima needs to animate boxes? Use OOBB in addition to AABB? | 174 | // here. Anima needs to animate boxes? Use OOBB in addition to AABB? |
175 | // | ||
176 | // TODO: Idea: when a model is loaded, compute an OOBB per joint using the | ||
177 | // vertices that are affected by the joint. Then transform this OOBB when | ||
178 | // animating the skeleton. Start with AABB for simplicity. The AABB/OOBB | ||
179 | // in the skeleton should be const. The transform AABB/OOBB is derived | ||
180 | // on demand. Stack allocator would be best for this kind of per-frame | ||
181 | // data. | ||
182 | // | ||
183 | // TODO: After computing joint AABB/OOBBs, check here whether the node has | ||
184 | // a skeleton, and if so, render the skeleton's boxes instead of the | ||
185 | // node's (the node's boxes are not animated, but computer from the rest | ||
186 | // pose). | ||
170 | const mat4 model = gfx_get_node_global_transform(node); | 187 | const mat4 model = gfx_get_node_global_transform(node); |
171 | const SceneObject* obj = gfx_get_node_object(node); | 188 | const SceneObject* obj = gfx_get_node_object(node); |
172 | const aabb3 box = gfx_calc_object_aabb(obj); | 189 | const aabb3 box = gfx_calc_object_aabb(obj); |
diff --git a/gfx/CMakeLists.txt b/gfx/CMakeLists.txt index 3aa3312..e5c965e 100644 --- a/gfx/CMakeLists.txt +++ b/gfx/CMakeLists.txt | |||
@@ -33,6 +33,7 @@ add_shader_library(shaders | |||
33 | shaders/view_texture.vert) | 33 | shaders/view_texture.vert) |
34 | 34 | ||
35 | add_library(gfx SHARED | 35 | add_library(gfx SHARED |
36 | src/asset/asset_cache.c | ||
36 | src/render/buffer.c | 37 | src/render/buffer.c |
37 | src/render/framebuffer.c | 38 | src/render/framebuffer.c |
38 | src/render/geometry.c | 39 | src/render/geometry.c |
diff --git a/gfx/include/gfx/asset.h b/gfx/include/gfx/asset.h new file mode 100644 index 0000000..28b8557 --- /dev/null +++ b/gfx/include/gfx/asset.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /* Asset Management */ | ||
2 | #pragma once | ||
3 | |||
4 | #include <gfx/render_backend.h> | ||
5 | |||
6 | #include <stddef.h> | ||
7 | |||
8 | typedef struct Gfx Gfx; | ||
9 | typedef struct SceneNode SceneNode; | ||
10 | typedef struct ShaderProgram ShaderProgram; | ||
11 | typedef struct Texture Texture; | ||
12 | |||
13 | /// Describes where the asset comes from. | ||
14 | typedef enum AssetOrigin { | ||
15 | AssetFromMemory, | ||
16 | AssetFromFile, | ||
17 | } AssetOrigin; | ||
18 | |||
19 | /// Describes a texture's colour space. | ||
20 | typedef enum TextureColourSpace { | ||
21 | sRGB, // The most likely default. | ||
22 | LinearColourSpace, | ||
23 | } TextureColourSpace; | ||
24 | |||
25 | /// Describes a command to load a texture. | ||
26 | typedef struct LoadTextureCmd { | ||
27 | AssetOrigin origin; | ||
28 | enum { LoadTexture, LoadCubemap } type; | ||
29 | TextureColourSpace colour_space; | ||
30 | TextureFiltering filtering; | ||
31 | TextureWrapping wrap; | ||
32 | bool mipmaps; | ||
33 | union { | ||
34 | // A single texture. | ||
35 | struct { | ||
36 | union { | ||
37 | struct { | ||
38 | mstring filepath; | ||
39 | }; | ||
40 | struct { | ||
41 | const void* data; | ||
42 | size_t size_bytes; | ||
43 | }; | ||
44 | }; | ||
45 | } texture; | ||
46 | // Cubemap texture. | ||
47 | struct { | ||
48 | union { | ||
49 | struct { | ||
50 | mstring filepath_pos_x; | ||
51 | mstring filepath_neg_x; | ||
52 | mstring filepath_pos_y; | ||
53 | mstring filepath_neg_y; | ||
54 | mstring filepath_pos_z; | ||
55 | mstring filepath_neg_z; | ||
56 | } filepaths; | ||
57 | struct { | ||
58 | const void* data_pos_x; | ||
59 | const void* data_neg_x; | ||
60 | const void* data_pos_y; | ||
61 | const void* data_neg_y; | ||
62 | const void* data_pos_z; | ||
63 | const void* data_neg_z; | ||
64 | } buffers; | ||
65 | }; | ||
66 | } cubemap; | ||
67 | } data; | ||
68 | } LoadTextureCmd; | ||
69 | |||
70 | /// Describes a command to load a scene. | ||
71 | typedef struct LoadSceneCmd { | ||
72 | AssetOrigin origin; | ||
73 | union { | ||
74 | struct { | ||
75 | mstring filepath; | ||
76 | }; | ||
77 | struct { | ||
78 | const void* data; | ||
79 | size_t size_bytes; | ||
80 | }; | ||
81 | }; | ||
82 | ShaderProgram* shader; | ||
83 | } LoadSceneCmd; | ||
84 | |||
85 | /// Load a scene. | ||
86 | /// | ||
87 | /// Return a top-level node under which scene elements are rooted. |root_node| | ||
88 | /// is made the parent of this top-level node. | ||
89 | /// | ||
90 | /// |shader| is an optional shader program assigned to the loaded scene objects. | ||
91 | /// If no shader is given, a Cook-Torrance shader based on the object's | ||
92 | /// characteristics (presence of normals, tangents, etc) is assigned. | ||
93 | /// | ||
94 | /// Currently only supports the GLTF format. | ||
95 | SceneNode* gfx_load_scene(Gfx*, SceneNode* root_node, const LoadSceneCmd*); | ||
96 | |||
97 | /// Load a texture. | ||
98 | Texture* gfx_load_texture(Gfx*, const LoadTextureCmd*); | ||
diff --git a/gfx/include/gfx/gfx.h b/gfx/include/gfx/gfx.h index b8f2595..bfc457f 100644 --- a/gfx/include/gfx/gfx.h +++ b/gfx/include/gfx/gfx.h | |||
@@ -1,10 +1,9 @@ | |||
1 | #pragma once | 1 | #pragma once |
2 | 2 | ||
3 | typedef struct AssetCache AssetCache; | ||
3 | typedef struct ImmRenderer ImmRenderer; | 4 | typedef struct ImmRenderer ImmRenderer; |
4 | typedef struct RenderBackend RenderBackend; | 5 | typedef struct RenderBackend RenderBackend; |
5 | typedef struct Renderer Renderer; | 6 | typedef struct Renderer Renderer; |
6 | typedef struct Scene Scene; | ||
7 | typedef struct SceneCamera SceneCamera; | ||
8 | 7 | ||
9 | typedef struct Gfx Gfx; | 8 | typedef struct Gfx Gfx; |
10 | 9 | ||
@@ -23,6 +22,9 @@ Renderer* gfx_get_renderer(Gfx*); | |||
23 | /// Get the immediate mode renderer. | 22 | /// Get the immediate mode renderer. |
24 | ImmRenderer* gfx_get_imm_renderer(Gfx*); | 23 | ImmRenderer* gfx_get_imm_renderer(Gfx*); |
25 | 24 | ||
25 | /// Get the asset cache. | ||
26 | AssetCache* gfx_get_asset_cache(Gfx*); | ||
27 | |||
26 | /// Remove unused resources from the scene (meshes, materials). | 28 | /// Remove unused resources from the scene (meshes, materials). |
27 | /// TODO: need to think about the interface for scene_purge(). Maybe this | 29 | /// TODO: need to think about the interface for scene_purge(). Maybe this |
28 | /// should be gfx_purge() and take a list of Scenes? | 30 | /// should be gfx_purge() and take a list of Scenes? |
diff --git a/gfx/include/gfx/sizes.h b/gfx/include/gfx/sizes.h index f2ace8a..b6f47ef 100644 --- a/gfx/include/gfx/sizes.h +++ b/gfx/include/gfx/sizes.h | |||
@@ -83,6 +83,10 @@ | |||
83 | /// Maximum number of matrices in the immediate-mode renderer's matrix stack. | 83 | /// Maximum number of matrices in the immediate-mode renderer's matrix stack. |
84 | #define IMM_MAX_NUM_MATRICES 32 | 84 | #define IMM_MAX_NUM_MATRICES 32 |
85 | 85 | ||
86 | // Asset Manager. | ||
87 | |||
88 | #define GFX_MAX_NUM_ASSETS 1024 | ||
89 | |||
86 | // Gfx. | 90 | // Gfx. |
87 | 91 | ||
88 | #define GFX_MAX_NUM_SCENES 4 | 92 | #define GFX_MAX_NUM_SCENES 4 |
diff --git a/gfx/include/gfx/util/scene.h b/gfx/include/gfx/util/scene.h index fa9304b..c03e2cb 100644 --- a/gfx/include/gfx/util/scene.h +++ b/gfx/include/gfx/util/scene.h | |||
@@ -1,26 +1,10 @@ | |||
1 | /// Load scene files. | 1 | /// Load scene files. |
2 | #pragma once | 2 | #pragma once |
3 | 3 | ||
4 | #include <stdbool.h> | 4 | #include <gfx/asset.h> |
5 | #include <stddef.h> | ||
6 | 5 | ||
7 | typedef struct Gfx Gfx; | 6 | typedef struct Gfx Gfx; |
8 | typedef struct SceneNode SceneNode; | 7 | typedef struct SceneNode SceneNode; |
9 | typedef struct ShaderProgram ShaderProgram; | ||
10 | |||
11 | typedef struct LoadSceneCmd { | ||
12 | enum { SceneFromMemory, SceneFromFile } origin; | ||
13 | union { | ||
14 | struct { | ||
15 | const char* filepath; | ||
16 | }; | ||
17 | struct { | ||
18 | const void* data; | ||
19 | size_t size_bytes; | ||
20 | }; | ||
21 | }; | ||
22 | ShaderProgram* shader; | ||
23 | } LoadSceneCmd; | ||
24 | 8 | ||
25 | /// Load a scene. | 9 | /// Load a scene. |
26 | /// | 10 | /// |
@@ -32,4 +16,4 @@ typedef struct LoadSceneCmd { | |||
32 | /// characteristics (presence of normals, tangents, etc) is assigned. | 16 | /// characteristics (presence of normals, tangents, etc) is assigned. |
33 | /// | 17 | /// |
34 | /// Currently only supports the GLTF format. | 18 | /// Currently only supports the GLTF format. |
35 | SceneNode* gfx_load_scene(Gfx*, SceneNode* root_node, const LoadSceneCmd*); | 19 | SceneNode* gfx_scene_load(Gfx*, SceneNode* root_node, const LoadSceneCmd*); |
diff --git a/gfx/include/gfx/util/texture.h b/gfx/include/gfx/util/texture.h index cdc582b..a3239fe 100644 --- a/gfx/include/gfx/util/texture.h +++ b/gfx/include/gfx/util/texture.h | |||
@@ -1,63 +1,7 @@ | |||
1 | /// Load textures from images. | 1 | /// Load textures from images. |
2 | #pragma once | 2 | #pragma once |
3 | 3 | ||
4 | #include <gfx/render_backend.h> | 4 | #include <gfx/asset.h> |
5 | 5 | ||
6 | #include <cstring.h> | 6 | /// Load a texture. |
7 | 7 | Texture* gfx_texture_load(RenderBackend*, const LoadTextureCmd*); | |
8 | #include <stdbool.h> | ||
9 | #include <stddef.h> | ||
10 | |||
11 | /// Describes a texture's colour space. | ||
12 | typedef enum TextureColourSpace { | ||
13 | sRGB, // The most likely default. | ||
14 | LinearColourSpace, | ||
15 | } TextureColourSpace; | ||
16 | |||
17 | /// Describes a command to load a texture. | ||
18 | typedef struct LoadTextureCmd { | ||
19 | enum { TextureFromMemory, TextureFromFile } origin; | ||
20 | enum { LoadTexture, LoadCubemap } type; | ||
21 | TextureColourSpace colour_space; | ||
22 | TextureFiltering filtering; | ||
23 | TextureWrapping wrap; | ||
24 | bool mipmaps; | ||
25 | union { | ||
26 | // A single texture. | ||
27 | struct { | ||
28 | union { | ||
29 | struct { | ||
30 | mstring filepath; | ||
31 | }; | ||
32 | struct { | ||
33 | const void* data; | ||
34 | size_t size_bytes; | ||
35 | }; | ||
36 | }; | ||
37 | } texture; | ||
38 | // Cubemap texture. | ||
39 | struct { | ||
40 | union { | ||
41 | struct { | ||
42 | mstring filepath_pos_x; | ||
43 | mstring filepath_neg_x; | ||
44 | mstring filepath_pos_y; | ||
45 | mstring filepath_neg_y; | ||
46 | mstring filepath_pos_z; | ||
47 | mstring filepath_neg_z; | ||
48 | } filepaths; | ||
49 | struct { | ||
50 | const void* data_pos_x; | ||
51 | const void* data_neg_x; | ||
52 | const void* data_pos_y; | ||
53 | const void* data_neg_y; | ||
54 | const void* data_pos_z; | ||
55 | const void* data_neg_z; | ||
56 | } buffers; | ||
57 | }; | ||
58 | } cubemap; | ||
59 | } data; | ||
60 | } LoadTextureCmd; | ||
61 | |||
62 | /// Load a cubemap texture. | ||
63 | Texture* gfx_load_texture(RenderBackend*, const LoadTextureCmd*); | ||
diff --git a/gfx/src/asset/asset_cache.c b/gfx/src/asset/asset_cache.c new file mode 100644 index 0000000..0c6a8dc --- /dev/null +++ b/gfx/src/asset/asset_cache.c | |||
@@ -0,0 +1,183 @@ | |||
1 | #include "asset_cache.h" | ||
2 | |||
3 | #include <gfx/asset.h> | ||
4 | #include <gfx/gfx.h> | ||
5 | #include <gfx/util/scene.h> | ||
6 | #include <gfx/util/texture.h> | ||
7 | |||
8 | #include <cstring.h> | ||
9 | #include <log/log.h> | ||
10 | |||
11 | #include <assert.h> | ||
12 | #include <stddef.h> | ||
13 | |||
14 | static Hash calc_scene_hash(const LoadSceneCmd* cmd) { | ||
15 | assert(cmd); | ||
16 | switch (cmd->origin) { | ||
17 | case AssetFromFile: | ||
18 | return cstring_hash(mstring_cstr(&cmd->filepath)); | ||
19 | case AssetFromMemory: | ||
20 | return (Hash)cmd->data; | ||
21 | } | ||
22 | assert(false); | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | static Hash calc_texture_hash(const LoadTextureCmd* cmd) { | ||
27 | assert(cmd); | ||
28 | switch (cmd->origin) { | ||
29 | case AssetFromFile: | ||
30 | switch (cmd->type) { | ||
31 | case LoadTexture: | ||
32 | return cstring_hash(mstring_cstr(&cmd->data.texture.filepath)); | ||
33 | case LoadCubemap: | ||
34 | return cstring_hash( | ||
35 | mstring_cstr(&cmd->data.cubemap.filepaths.filepath_pos_x)) ^ | ||
36 | cstring_hash( | ||
37 | mstring_cstr(&cmd->data.cubemap.filepaths.filepath_neg_x)) ^ | ||
38 | cstring_hash( | ||
39 | mstring_cstr(&cmd->data.cubemap.filepaths.filepath_pos_y)) ^ | ||
40 | cstring_hash( | ||
41 | mstring_cstr(&cmd->data.cubemap.filepaths.filepath_neg_y)) ^ | ||
42 | cstring_hash( | ||
43 | mstring_cstr(&cmd->data.cubemap.filepaths.filepath_pos_z)) ^ | ||
44 | cstring_hash( | ||
45 | mstring_cstr(&cmd->data.cubemap.filepaths.filepath_neg_z)); | ||
46 | } | ||
47 | break; | ||
48 | case AssetFromMemory: | ||
49 | switch (cmd->type) { | ||
50 | case LoadTexture: | ||
51 | return (Hash)cmd->data.texture.data; | ||
52 | case LoadCubemap: | ||
53 | return (Hash)cmd->data.cubemap.buffers.data_pos_x ^ | ||
54 | (Hash)cmd->data.cubemap.buffers.data_neg_x ^ | ||
55 | (Hash)cmd->data.cubemap.buffers.data_pos_y ^ | ||
56 | (Hash)cmd->data.cubemap.buffers.data_neg_y ^ | ||
57 | (Hash)cmd->data.cubemap.buffers.data_pos_z ^ | ||
58 | (Hash)cmd->data.cubemap.buffers.data_neg_z; | ||
59 | } | ||
60 | break; | ||
61 | } | ||
62 | assert(false); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static Asset* lookup_cache(AssetCache* cache, Hash hash) { | ||
67 | assert(cache); | ||
68 | mempool_foreach(&cache->assets, asset, { | ||
69 | if (asset->hash == hash) { | ||
70 | return asset; | ||
71 | } | ||
72 | }); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | // TODO: questionable function. Make mempool_alloc() fail when out of memory. | ||
77 | static void insert_into_cache(AssetCache* cache, const Asset* asset) { | ||
78 | assert(cache); | ||
79 | assert(asset); | ||
80 | Asset* poolAsset = mempool_alloc(&cache->assets); | ||
81 | assert(asset); | ||
82 | *poolAsset = *asset; | ||
83 | } | ||
84 | |||
85 | static void log_scene_cache_hit(const LoadSceneCmd* cmd, Hash hash) { | ||
86 | assert(cmd); | ||
87 | switch (cmd->origin) { | ||
88 | case AssetFromFile: | ||
89 | LOGI( | ||
90 | "Found asset [%s] in cache with hash [%lu]", | ||
91 | mstring_cstr(&cmd->filepath), hash); | ||
92 | break; | ||
93 | case AssetFromMemory: | ||
94 | LOGI("Found asset [%p] in cache with hash [%lu]", cmd->data, hash); | ||
95 | break; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | static void log_scene_loaded(const LoadSceneCmd* cmd) { | ||
100 | assert(cmd); | ||
101 | switch (cmd->origin) { | ||
102 | case AssetFromFile: | ||
103 | LOGI("Loaded asset from file: [%s]", mstring_cstr(&cmd->filepath)); | ||
104 | break; | ||
105 | case AssetFromMemory: | ||
106 | LOGI("Loaded asset from memory: [%p]", cmd->data); | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | void gfx_init_asset_cache(AssetCache* cache) { | ||
112 | assert(cache); | ||
113 | mempool_make(&cache->assets); | ||
114 | |||
115 | // Allocate a dummy asset at index 0 to guarantee that no assets allocated by | ||
116 | // the caller map to index 0. | ||
117 | const Asset* dummy = mempool_alloc(&cache->assets); | ||
118 | assert(mempool_get_block_index(&cache->assets, dummy) == 0); | ||
119 | } | ||
120 | |||
121 | void gfx_destroy_asset_cache(AssetCache* cache) { | ||
122 | assert(cache); | ||
123 | mempool_del(&cache->assets); | ||
124 | } | ||
125 | |||
126 | SceneNode* gfx_load_scene( | ||
127 | Gfx* gfx, SceneNode* root_node, const LoadSceneCmd* cmd) { | ||
128 | assert(gfx); | ||
129 | |||
130 | AssetCache* cache = gfx_get_asset_cache(gfx); | ||
131 | |||
132 | // First search for the asset in the cache. | ||
133 | // TODO: Animated models are currently mutated in place, so sharing them is | ||
134 | // not really valid. | ||
135 | const uint64_t hash = calc_scene_hash(cmd); | ||
136 | Asset* asset = lookup_cache(cache, hash); | ||
137 | if (asset) { | ||
138 | log_scene_cache_hit(cmd, hash); | ||
139 | return (SceneNode*)asset; | ||
140 | } | ||
141 | |||
142 | // Asset not found in the cache. | ||
143 | // Load it, insert it into the cache, and return it. | ||
144 | SceneNode* node = gfx_scene_load(gfx, root_node, cmd); | ||
145 | if (node) { | ||
146 | insert_into_cache( | ||
147 | cache, &(Asset){ | ||
148 | .type = SceneAsset, | ||
149 | .hash = hash, | ||
150 | .data = node, | ||
151 | }); | ||
152 | log_scene_loaded(cmd); | ||
153 | } | ||
154 | return node; | ||
155 | } | ||
156 | |||
157 | Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) { | ||
158 | assert(gfx); | ||
159 | assert(cmd); | ||
160 | |||
161 | AssetCache* cache = gfx_get_asset_cache(gfx); | ||
162 | |||
163 | // First search for the asset in the cache. | ||
164 | const uint64_t hash = calc_texture_hash(cmd); | ||
165 | Asset* asset = lookup_cache(cache, hash); | ||
166 | if (asset) { | ||
167 | return (Texture*)asset; | ||
168 | } | ||
169 | |||
170 | // Asset not found in the cache. | ||
171 | // Load it, insert it into the cache, and return it. | ||
172 | RenderBackend* render_backend = gfx_get_render_backend(gfx); | ||
173 | Texture* texture = gfx_texture_load(render_backend, cmd); | ||
174 | if (texture) { | ||
175 | insert_into_cache( | ||
176 | cache, &(Asset){ | ||
177 | .type = TextureAsset, | ||
178 | .hash = hash, | ||
179 | .data = texture, | ||
180 | }); | ||
181 | } | ||
182 | return texture; | ||
183 | } | ||
diff --git a/gfx/src/asset/asset_cache.h b/gfx/src/asset/asset_cache.h new file mode 100644 index 0000000..04baa51 --- /dev/null +++ b/gfx/src/asset/asset_cache.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <gfx/sizes.h> | ||
4 | |||
5 | #include <cstring.h> | ||
6 | #include <mempool.h> | ||
7 | |||
8 | typedef uint64_t Hash; | ||
9 | |||
10 | typedef enum AssetType { | ||
11 | SceneAsset, | ||
12 | TextureAsset, | ||
13 | } AssetType; | ||
14 | |||
15 | typedef struct Asset { | ||
16 | AssetType type; | ||
17 | Hash hash; | ||
18 | void* data; | ||
19 | } Asset; | ||
20 | |||
21 | DEF_MEMPOOL(asset_pool, Asset, GFX_MAX_NUM_ASSETS) | ||
22 | |||
23 | typedef struct AssetCache { | ||
24 | asset_pool assets; | ||
25 | } AssetCache; | ||
26 | |||
27 | /// Create a new asset cache. | ||
28 | void gfx_init_asset_cache(AssetCache*); | ||
29 | |||
30 | /// Destroy the asset cache. | ||
31 | void gfx_destroy_asset_cache(AssetCache*); | ||
diff --git a/gfx/src/gfx.c b/gfx/src/gfx.c index fc720ed..7095ea1 100644 --- a/gfx/src/gfx.c +++ b/gfx/src/gfx.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <gfx/gfx.h> | 1 | #include <gfx/gfx.h> |
2 | 2 | ||
3 | #include "asset/asset_cache.h" | ||
3 | #include "render/render_backend_impl.h" | 4 | #include "render/render_backend_impl.h" |
4 | #include "renderer/imm_renderer_impl.h" | 5 | #include "renderer/imm_renderer_impl.h" |
5 | #include "renderer/renderer_impl.h" | 6 | #include "renderer/renderer_impl.h" |
@@ -14,6 +15,7 @@ | |||
14 | #include <stdlib.h> | 15 | #include <stdlib.h> |
15 | 16 | ||
16 | typedef struct Gfx { | 17 | typedef struct Gfx { |
18 | AssetCache asset_cache; | ||
17 | RenderBackend render_backend; | 19 | RenderBackend render_backend; |
18 | Renderer renderer; | 20 | Renderer renderer; |
19 | ImmRenderer imm_renderer; | 21 | ImmRenderer imm_renderer; |
@@ -40,16 +42,17 @@ Gfx* gfx_init(void) { | |||
40 | gfx_destroy(&gfx); | 42 | gfx_destroy(&gfx); |
41 | return 0; | 43 | return 0; |
42 | } | 44 | } |
45 | gfx_init_asset_cache(&gfx->asset_cache); | ||
43 | scene_mem_init(); | 46 | scene_mem_init(); |
44 | return gfx; | 47 | return gfx; |
45 | } | 48 | } |
46 | 49 | ||
47 | void gfx_destroy(Gfx** gfx) { | 50 | void gfx_destroy(Gfx** gfx) { |
48 | assert(gfx); | ||
49 | if (!gfx) { | 51 | if (!gfx) { |
50 | return; | 52 | return; |
51 | } | 53 | } |
52 | scene_mem_destroy(); | 54 | scene_mem_destroy(); |
55 | gfx_destroy_asset_cache(&(*gfx)->asset_cache); | ||
53 | renderer_destroy(&(*gfx)->renderer); | 56 | renderer_destroy(&(*gfx)->renderer); |
54 | imm_renderer_destroy(&(*gfx)->imm_renderer); | 57 | imm_renderer_destroy(&(*gfx)->imm_renderer); |
55 | gfx_del_render_backend(&(*gfx)->render_backend); | 58 | gfx_del_render_backend(&(*gfx)->render_backend); |
@@ -71,3 +74,8 @@ ImmRenderer* gfx_get_imm_renderer(Gfx* gfx) { | |||
71 | assert(gfx); | 74 | assert(gfx); |
72 | return &gfx->imm_renderer; | 75 | return &gfx->imm_renderer; |
73 | } | 76 | } |
77 | |||
78 | AssetCache* gfx_get_asset_cache(Gfx* gfx) { | ||
79 | assert(gfx); | ||
80 | return &gfx->asset_cache; | ||
81 | } | ||
diff --git a/gfx/src/util/scene.c b/gfx/src/util/scene.c index 5d79cf2..5bf45aa 100644 --- a/gfx/src/util/scene.c +++ b/gfx/src/util/scene.c | |||
@@ -655,7 +655,7 @@ static void load_textures_lazy( | |||
655 | mstring_concat_path(mstring_make(directory), mstring_make(image->uri)); | 655 | mstring_concat_path(mstring_make(directory), mstring_make(image->uri)); |
656 | 656 | ||
657 | load_texture_cmds[i] = (LoadTextureCmd){ | 657 | load_texture_cmds[i] = (LoadTextureCmd){ |
658 | .origin = TextureFromFile, | 658 | .origin = AssetFromFile, |
659 | .type = LoadTexture, | 659 | .type = LoadTexture, |
660 | .colour_space = sRGB, | 660 | .colour_space = sRGB, |
661 | .filtering = filtering, | 661 | .filtering = filtering, |
@@ -670,12 +670,11 @@ static void load_textures_lazy( | |||
670 | /// This determines a texture's colour space based on its intended use, loads | 670 | /// This determines a texture's colour space based on its intended use, loads |
671 | /// the texture, and then defines the sampler shader uniform. | 671 | /// the texture, and then defines the sampler shader uniform. |
672 | static bool load_texture_and_uniform( | 672 | static bool load_texture_and_uniform( |
673 | const cgltf_data* data, RenderBackend* render_backend, | 673 | const cgltf_data* data, Gfx* gfx, const cgltf_texture_view* texture_view, |
674 | const cgltf_texture_view* texture_view, TextureType texture_type, | 674 | TextureType texture_type, Texture** textures, |
675 | Texture** textures, LoadTextureCmd* load_texture_cmds, int* next_uniform, | 675 | LoadTextureCmd* load_texture_cmds, int* next_uniform, MaterialDesc* desc) { |
676 | MaterialDesc* desc) { | ||
677 | assert(data); | 676 | assert(data); |
678 | assert(render_backend); | 677 | assert(gfx); |
679 | assert(texture_view); | 678 | assert(texture_view); |
680 | assert(textures); | 679 | assert(textures); |
681 | assert(next_uniform); | 680 | assert(next_uniform); |
@@ -700,7 +699,7 @@ static bool load_texture_and_uniform( | |||
700 | mstring_cstr(&cmd->data.texture.filepath), cmd->mipmaps, | 699 | mstring_cstr(&cmd->data.texture.filepath), cmd->mipmaps, |
701 | cmd->filtering); | 700 | cmd->filtering); |
702 | 701 | ||
703 | textures[texture_index] = gfx_load_texture(render_backend, cmd); | 702 | textures[texture_index] = gfx_load_texture(gfx, cmd); |
704 | if (!textures[texture_index]) { | 703 | if (!textures[texture_index]) { |
705 | prepend_error( | 704 | prepend_error( |
706 | "Failed to load texture: %s", | 705 | "Failed to load texture: %s", |
@@ -724,11 +723,10 @@ static bool load_texture_and_uniform( | |||
724 | /// the index of each glTF material in the scene. Also return the number of | 723 | /// the index of each glTF material in the scene. Also return the number of |
725 | /// materials and the textures used by them. | 724 | /// materials and the textures used by them. |
726 | static bool load_materials( | 725 | static bool load_materials( |
727 | const cgltf_data* data, RenderBackend* render_backend, | 726 | const cgltf_data* data, Gfx* gfx, LoadTextureCmd* load_texture_cmds, |
728 | LoadTextureCmd* load_texture_cmds, Texture** textures, | 727 | Texture** textures, Material** materials) { |
729 | Material** materials) { | ||
730 | assert(data); | 728 | assert(data); |
731 | assert(render_backend); | 729 | assert(gfx); |
732 | assert(materials); | 730 | assert(materials); |
733 | if (data->textures_count > 0) { | 731 | if (data->textures_count > 0) { |
734 | assert(load_texture_cmds); | 732 | assert(load_texture_cmds); |
@@ -771,16 +769,15 @@ static bool load_materials( | |||
771 | 769 | ||
772 | if (pbr->base_color_texture.texture) { | 770 | if (pbr->base_color_texture.texture) { |
773 | if (!load_texture_and_uniform( | 771 | if (!load_texture_and_uniform( |
774 | data, render_backend, &pbr->base_color_texture, | 772 | data, gfx, &pbr->base_color_texture, BaseColorTexture, textures, |
775 | BaseColorTexture, textures, load_texture_cmds, &next_uniform, | 773 | load_texture_cmds, &next_uniform, &desc)) { |
776 | &desc)) { | ||
777 | return false; | 774 | return false; |
778 | } | 775 | } |
779 | } | 776 | } |
780 | 777 | ||
781 | if (pbr->metallic_roughness_texture.texture) { | 778 | if (pbr->metallic_roughness_texture.texture) { |
782 | if (!load_texture_and_uniform( | 779 | if (!load_texture_and_uniform( |
783 | data, render_backend, &pbr->metallic_roughness_texture, | 780 | data, gfx, &pbr->metallic_roughness_texture, |
784 | MetallicRoughnessTexture, textures, load_texture_cmds, | 781 | MetallicRoughnessTexture, textures, load_texture_cmds, |
785 | &next_uniform, &desc)) { | 782 | &next_uniform, &desc)) { |
786 | return false; | 783 | return false; |
@@ -790,24 +787,23 @@ static bool load_materials( | |||
790 | 787 | ||
791 | if (mat->emissive_texture.texture) { | 788 | if (mat->emissive_texture.texture) { |
792 | if (!load_texture_and_uniform( | 789 | if (!load_texture_and_uniform( |
793 | data, render_backend, &mat->emissive_texture, EmissiveTexture, | 790 | data, gfx, &mat->emissive_texture, EmissiveTexture, textures, |
794 | textures, load_texture_cmds, &next_uniform, &desc)) { | 791 | load_texture_cmds, &next_uniform, &desc)) { |
795 | return false; | 792 | return false; |
796 | } | 793 | } |
797 | } | 794 | } |
798 | 795 | ||
799 | if (mat->occlusion_texture.texture) { | 796 | if (mat->occlusion_texture.texture) { |
800 | if (!load_texture_and_uniform( | 797 | if (!load_texture_and_uniform( |
801 | data, render_backend, &mat->occlusion_texture, | 798 | data, gfx, &mat->occlusion_texture, AmbientOcclusionTexture, |
802 | AmbientOcclusionTexture, textures, load_texture_cmds, | 799 | textures, load_texture_cmds, &next_uniform, &desc)) { |
803 | &next_uniform, &desc)) { | ||
804 | return false; | 800 | return false; |
805 | } | 801 | } |
806 | } | 802 | } |
807 | 803 | ||
808 | if (mat->normal_texture.texture) { | 804 | if (mat->normal_texture.texture) { |
809 | if (!load_texture_and_uniform( | 805 | if (!load_texture_and_uniform( |
810 | data, render_backend, &mat->normal_texture, NormalMap, textures, | 806 | data, gfx, &mat->normal_texture, NormalMap, textures, |
811 | load_texture_cmds, &next_uniform, &desc)) { | 807 | load_texture_cmds, &next_uniform, &desc)) { |
812 | return false; | 808 | return false; |
813 | } | 809 | } |
@@ -878,7 +874,7 @@ aabb3 compute_aabb(const cgltf_accessor* accessor, int dim) { | |||
878 | 874 | ||
879 | /// Load all meshes from the glTF scene. | 875 | /// Load all meshes from the glTF scene. |
880 | static bool load_meshes( | 876 | static bool load_meshes( |
881 | const cgltf_data* data, Gfx* gfx, Buffer** buffers, | 877 | const cgltf_data* data, RenderBackend* render_backend, Buffer** buffers, |
882 | Buffer** tangent_buffers, const cgltfTangentBuffer* cgltf_tangent_buffers, | 878 | Buffer** tangent_buffers, const cgltfTangentBuffer* cgltf_tangent_buffers, |
883 | cgltf_size num_tangent_buffers, Material** materials, | 879 | cgltf_size num_tangent_buffers, Material** materials, |
884 | ShaderProgram* const shader, size_t primitive_count, Geometry** geometries, | 880 | ShaderProgram* const shader, size_t primitive_count, Geometry** geometries, |
@@ -894,7 +890,7 @@ static bool load_meshes( | |||
894 | // Accessor + buffer view BufferView | 890 | // Accessor + buffer view BufferView |
895 | // Buffer Buffer | 891 | // Buffer Buffer |
896 | assert(data); | 892 | assert(data); |
897 | assert(gfx); | 893 | assert(render_backend); |
898 | assert(buffers); | 894 | assert(buffers); |
899 | assert(materials); | 895 | assert(materials); |
900 | assert(geometries); | 896 | assert(geometries); |
@@ -905,9 +901,6 @@ static bool load_meshes( | |||
905 | assert(cgltf_tangent_buffers); | 901 | assert(cgltf_tangent_buffers); |
906 | } | 902 | } |
907 | 903 | ||
908 | // TODO: pass render_backend as argument instead of gfx. | ||
909 | RenderBackend* render_backend = gfx_get_render_backend(gfx); | ||
910 | |||
911 | // Points to the next available Mesh and also the next available Geometry. | 904 | // Points to the next available Mesh and also the next available Geometry. |
912 | // There is one (Mesh, Geometry) pair per glTF mesh primitive. | 905 | // There is one (Mesh, Geometry) pair per glTF mesh primitive. |
913 | size_t next_mesh = 0; | 906 | size_t next_mesh = 0; |
@@ -1331,6 +1324,10 @@ static void load_nodes( | |||
1331 | assert(skin_index < data->skins_count); | 1324 | assert(skin_index < data->skins_count); |
1332 | const Skeleton* skeleton = gfx_get_anima_skeleton(anima, skin_index); | 1325 | const Skeleton* skeleton = gfx_get_anima_skeleton(anima, skin_index); |
1333 | gfx_set_object_skeleton(object, skeleton); | 1326 | gfx_set_object_skeleton(object, skeleton); |
1327 | |||
1328 | // TODO: Compute AABBs/OOBBs for the skeleton's joints here. Iterate | ||
1329 | // over the mesh's primitives, its vertices, their joint indices, and | ||
1330 | // add the vertex to the AABB/OOBB. | ||
1334 | } | 1331 | } |
1335 | } else if (node->camera) { | 1332 | } else if (node->camera) { |
1336 | assert(next_camera < data->cameras_count); | 1333 | assert(next_camera < data->cameras_count); |
@@ -1409,7 +1406,7 @@ static void load_nodes( | |||
1409 | /// This function ignores the many scenes and default scene of the glTF spec | 1406 | /// This function ignores the many scenes and default scene of the glTF spec |
1410 | /// and instead just loads all scenes into a single gfx Scene. | 1407 | /// and instead just loads all scenes into a single gfx Scene. |
1411 | static SceneNode* load_scene( | 1408 | static SceneNode* load_scene( |
1412 | cgltf_data* data, Gfx* gfx, SceneNode* root_node, const char* filepath, | 1409 | cgltf_data* data, Gfx* gfx, SceneNode* root_node, const mstring* filepath, |
1413 | ShaderProgram* shader, const cgltfTangentBuffer* cgltf_tangent_buffers, | 1410 | ShaderProgram* shader, const cgltfTangentBuffer* cgltf_tangent_buffers, |
1414 | cgltf_size num_tangent_buffers) { | 1411 | cgltf_size num_tangent_buffers) { |
1415 | // In a GLTF scene, buffers can be shared among meshes, meshes among nodes, | 1412 | // In a GLTF scene, buffers can be shared among meshes, meshes among nodes, |
@@ -1437,8 +1434,8 @@ static SceneNode* load_scene( | |||
1437 | RenderBackend* render_backend = gfx_get_render_backend(gfx); | 1434 | RenderBackend* render_backend = gfx_get_render_backend(gfx); |
1438 | const size_t primitive_count = get_total_primitives(data); | 1435 | const size_t primitive_count = get_total_primitives(data); |
1439 | 1436 | ||
1440 | const mstring directory = mstring_dirname(mstring_make(filepath)); | 1437 | const mstring directory = mstring_dirname(*filepath); |
1441 | LOGD("Filepath: %s", filepath); | 1438 | LOGD("Filepath: %s", mstring_cstr(filepath)); |
1442 | LOGD("Directory: %s", mstring_cstr(&directory)); | 1439 | LOGD("Directory: %s", mstring_cstr(&directory)); |
1443 | 1440 | ||
1444 | Buffer** tangent_buffers = 0; | 1441 | Buffer** tangent_buffers = 0; |
@@ -1494,13 +1491,12 @@ static SceneNode* load_scene( | |||
1494 | data, render_backend, mstring_cstr(&directory), load_texture_cmds); | 1491 | data, render_backend, mstring_cstr(&directory), load_texture_cmds); |
1495 | } | 1492 | } |
1496 | 1493 | ||
1497 | if (!load_materials( | 1494 | if (!load_materials(data, gfx, load_texture_cmds, textures, materials)) { |
1498 | data, render_backend, load_texture_cmds, textures, materials)) { | ||
1499 | goto cleanup; | 1495 | goto cleanup; |
1500 | } | 1496 | } |
1501 | 1497 | ||
1502 | if (!load_meshes( | 1498 | if (!load_meshes( |
1503 | data, gfx, buffers, tangent_buffers, cgltf_tangent_buffers, | 1499 | data, render_backend, buffers, tangent_buffers, cgltf_tangent_buffers, |
1504 | num_tangent_buffers, materials, shader, primitive_count, geometries, | 1500 | num_tangent_buffers, materials, shader, primitive_count, geometries, |
1505 | meshes, scene_objects)) { | 1501 | meshes, scene_objects)) { |
1506 | goto cleanup; | 1502 | goto cleanup; |
@@ -1639,7 +1635,7 @@ cleanup: | |||
1639 | return anima_node; | 1635 | return anima_node; |
1640 | } | 1636 | } |
1641 | 1637 | ||
1642 | SceneNode* gfx_load_scene( | 1638 | SceneNode* gfx_scene_load( |
1643 | Gfx* gfx, SceneNode* root_node, const LoadSceneCmd* cmd) { | 1639 | Gfx* gfx, SceneNode* root_node, const LoadSceneCmd* cmd) { |
1644 | assert(gfx); | 1640 | assert(gfx); |
1645 | assert(root_node); | 1641 | assert(root_node); |
@@ -1653,10 +1649,10 @@ SceneNode* gfx_load_scene( | |||
1653 | 1649 | ||
1654 | cgltf_result result; | 1650 | cgltf_result result; |
1655 | switch (cmd->origin) { | 1651 | switch (cmd->origin) { |
1656 | case SceneFromFile: | 1652 | case AssetFromFile: |
1657 | result = cgltf_parse_file(&options, cmd->filepath, &data); | 1653 | result = cgltf_parse_file(&options, mstring_cstr(&cmd->filepath), &data); |
1658 | break; | 1654 | break; |
1659 | case SceneFromMemory: | 1655 | case AssetFromMemory: |
1660 | result = cgltf_parse(&options, cmd->data, cmd->size_bytes, &data); | 1656 | result = cgltf_parse(&options, cmd->data, cmd->size_bytes, &data); |
1661 | break; | 1657 | break; |
1662 | } | 1658 | } |
@@ -1664,9 +1660,9 @@ SceneNode* gfx_load_scene( | |||
1664 | goto cleanup; | 1660 | goto cleanup; |
1665 | } | 1661 | } |
1666 | 1662 | ||
1667 | if (cmd->origin == SceneFromFile) { | 1663 | if (cmd->origin == AssetFromFile) { |
1668 | // Must call cgltf_load_buffers() to load buffer data. | 1664 | // Must call cgltf_load_buffers() to load buffer data. |
1669 | result = cgltf_load_buffers(&options, data, cmd->filepath); | 1665 | result = cgltf_load_buffers(&options, data, mstring_cstr(&cmd->filepath)); |
1670 | if (result != cgltf_result_success) { | 1666 | if (result != cgltf_result_success) { |
1671 | goto cleanup; | 1667 | goto cleanup; |
1672 | } | 1668 | } |
@@ -1678,7 +1674,7 @@ SceneNode* gfx_load_scene( | |||
1678 | &options, data, &tangent_buffers, &num_tangent_buffers); | 1674 | &options, data, &tangent_buffers, &num_tangent_buffers); |
1679 | 1675 | ||
1680 | scene_node = load_scene( | 1676 | scene_node = load_scene( |
1681 | data, gfx, root_node, cmd->filepath, cmd->shader, tangent_buffers, | 1677 | data, gfx, root_node, &cmd->filepath, cmd->shader, tangent_buffers, |
1682 | num_tangent_buffers); | 1678 | num_tangent_buffers); |
1683 | 1679 | ||
1684 | cleanup: | 1680 | cleanup: |
diff --git a/gfx/src/util/texture.c b/gfx/src/util/texture.c index 23f15f0..0d2e4b8 100644 --- a/gfx/src/util/texture.c +++ b/gfx/src/util/texture.c | |||
@@ -43,18 +43,18 @@ static void flip_horizontally( | |||
43 | // For this reason, we do X and Y flips when doing cubemap textures so that we | 43 | // For this reason, we do X and Y flips when doing cubemap textures so that we |
44 | // can sample cubemaps as if they were given in the usual OpenGL coordinate | 44 | // can sample cubemaps as if they were given in the usual OpenGL coordinate |
45 | // system. | 45 | // system. |
46 | Texture* gfx_load_texture( | 46 | Texture* gfx_texture_load( |
47 | RenderBackend* render_backend, const LoadTextureCmd* cmd) { | 47 | RenderBackend* render_backend, const LoadTextureCmd* cmd) { |
48 | assert(render_backend); | 48 | assert(render_backend); |
49 | assert(cmd); | 49 | assert(cmd); |
50 | assert(cmd->origin == TextureFromFile || cmd->origin == TextureFromMemory); | 50 | assert(cmd->origin == AssetFromFile || cmd->origin == AssetFromMemory); |
51 | assert(cmd->type == LoadTexture || cmd->type == LoadCubemap); | 51 | assert(cmd->type == LoadTexture || cmd->type == LoadCubemap); |
52 | 52 | ||
53 | int width, height, components, old_components; | 53 | int width, height, components, old_components; |
54 | unsigned char* pixels[6] = {0}; | 54 | unsigned char* pixels[6] = {0}; |
55 | 55 | ||
56 | switch (cmd->origin) { | 56 | switch (cmd->origin) { |
57 | case TextureFromFile: | 57 | case AssetFromFile: |
58 | switch (cmd->type) { | 58 | switch (cmd->type) { |
59 | case LoadTexture: { | 59 | case LoadTexture: { |
60 | const char* filepath = mstring_cstr(&cmd->data.texture.filepath); | 60 | const char* filepath = mstring_cstr(&cmd->data.texture.filepath); |
@@ -91,7 +91,7 @@ Texture* gfx_load_texture( | |||
91 | break; | 91 | break; |
92 | } | 92 | } |
93 | break; | 93 | break; |
94 | case TextureFromMemory: | 94 | case AssetFromMemory: |
95 | // TODO: Load textures from memory. | 95 | // TODO: Load textures from memory. |
96 | set_error("Loading textures from memory is not yet implemented"); | 96 | set_error("Loading textures from memory is not yet implemented"); |
97 | return 0; | 97 | return 0; |