summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gfx/CMakeLists.txt1
-rw-r--r--gfx/src/asset/asset_cache.c47
-rw-r--r--gfx/src/gfx_assert.h5
-rw-r--r--gfx/src/render/buffer.c8
-rw-r--r--gfx/src/render/framebuffer.c4
-rw-r--r--gfx/src/render/geometry.c9
-rw-r--r--gfx/src/render/render_backend.c107
-rw-r--r--gfx/src/render/renderbuffer.c1
-rw-r--r--gfx/src/render/shader.c8
-rw-r--r--gfx/src/render/shader_program.c21
-rw-r--r--gfx/src/render/texture.c19
-rw-r--r--gfx/src/scene/animation.c72
-rw-r--r--gfx/src/scene/camera.c25
-rw-r--r--gfx/src/scene/light.c13
-rw-r--r--gfx/src/scene/material.c3
-rw-r--r--gfx/src/scene/mesh.c3
-rw-r--r--gfx/src/scene/node.c73
-rw-r--r--gfx/src/scene/object.c16
-rw-r--r--gfx/src/scene/scene.c13
19 files changed, 204 insertions, 244 deletions
diff --git a/gfx/CMakeLists.txt b/gfx/CMakeLists.txt
index e5c965e..2b295d5 100644
--- a/gfx/CMakeLists.txt
+++ b/gfx/CMakeLists.txt
@@ -74,6 +74,7 @@ target_link_libraries(gfx PUBLIC
74 math) 74 math)
75 75
76target_link_libraries(gfx PRIVATE 76target_link_libraries(gfx PRIVATE
77 cassert
77 cgltf 78 cgltf
78 cgltf-tangents 79 cgltf-tangents
79 error 80 error
diff --git a/gfx/src/asset/asset_cache.c b/gfx/src/asset/asset_cache.c
index 0c6a8dc..2fa57ad 100644
--- a/gfx/src/asset/asset_cache.c
+++ b/gfx/src/asset/asset_cache.c
@@ -4,13 +4,11 @@
4#include <gfx/gfx.h> 4#include <gfx/gfx.h>
5#include <gfx/util/scene.h> 5#include <gfx/util/scene.h>
6#include <gfx/util/texture.h> 6#include <gfx/util/texture.h>
7#include <gfx_assert.h>
7 8
8#include <cstring.h> 9#include <cstring.h>
9#include <log/log.h> 10#include <log/log.h>
10 11
11#include <assert.h>
12#include <stddef.h>
13
14static Hash calc_scene_hash(const LoadSceneCmd* cmd) { 12static Hash calc_scene_hash(const LoadSceneCmd* cmd) {
15 assert(cmd); 13 assert(cmd);
16 switch (cmd->origin) { 14 switch (cmd->origin) {
@@ -19,7 +17,7 @@ static Hash calc_scene_hash(const LoadSceneCmd* cmd) {
19 case AssetFromMemory: 17 case AssetFromMemory:
20 return (Hash)cmd->data; 18 return (Hash)cmd->data;
21 } 19 }
22 assert(false); 20 FAIL("Unhandled scene asset origin");
23 return 0; 21 return 0;
24} 22}
25 23
@@ -59,7 +57,7 @@ static Hash calc_texture_hash(const LoadTextureCmd* cmd) {
59 } 57 }
60 break; 58 break;
61 } 59 }
62 assert(false); 60 FAIL("Unhandled texture asset origin");
63 return 0; 61 return 0;
64} 62}
65 63
@@ -73,25 +71,16 @@ static Asset* lookup_cache(AssetCache* cache, Hash hash) {
73 return 0; 71 return 0;
74} 72}
75 73
76// TODO: questionable function. Make mempool_alloc() fail when out of memory.
77static 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
85static void log_scene_cache_hit(const LoadSceneCmd* cmd, Hash hash) { 74static void log_scene_cache_hit(const LoadSceneCmd* cmd, Hash hash) {
86 assert(cmd); 75 assert(cmd);
87 switch (cmd->origin) { 76 switch (cmd->origin) {
88 case AssetFromFile: 77 case AssetFromFile:
89 LOGI( 78 LOGD(
90 "Found asset [%s] in cache with hash [%lu]", 79 "Found asset [%s] in cache with hash [%lu]",
91 mstring_cstr(&cmd->filepath), hash); 80 mstring_cstr(&cmd->filepath), hash);
92 break; 81 break;
93 case AssetFromMemory: 82 case AssetFromMemory:
94 LOGI("Found asset [%p] in cache with hash [%lu]", cmd->data, hash); 83 LOGD("Found asset [%p] in cache with hash [%lu]", cmd->data, hash);
95 break; 84 break;
96 } 85 }
97} 86}
@@ -100,10 +89,10 @@ static void log_scene_loaded(const LoadSceneCmd* cmd) {
100 assert(cmd); 89 assert(cmd);
101 switch (cmd->origin) { 90 switch (cmd->origin) {
102 case AssetFromFile: 91 case AssetFromFile:
103 LOGI("Loaded asset from file: [%s]", mstring_cstr(&cmd->filepath)); 92 LOGD("Loaded asset from file: [%s]", mstring_cstr(&cmd->filepath));
104 break; 93 break;
105 case AssetFromMemory: 94 case AssetFromMemory:
106 LOGI("Loaded asset from memory: [%p]", cmd->data); 95 LOGD("Loaded asset from memory: [%p]", cmd->data);
107 break; 96 break;
108 } 97 }
109} 98}
@@ -143,12 +132,11 @@ SceneNode* gfx_load_scene(
143 // Load it, insert it into the cache, and return it. 132 // Load it, insert it into the cache, and return it.
144 SceneNode* node = gfx_scene_load(gfx, root_node, cmd); 133 SceneNode* node = gfx_scene_load(gfx, root_node, cmd);
145 if (node) { 134 if (node) {
146 insert_into_cache( 135 *(Asset*)mempool_alloc(&cache->assets) = (Asset){
147 cache, &(Asset){ 136 .type = SceneAsset,
148 .type = SceneAsset, 137 .hash = hash,
149 .hash = hash, 138 .data = node,
150 .data = node, 139 };
151 });
152 log_scene_loaded(cmd); 140 log_scene_loaded(cmd);
153 } 141 }
154 return node; 142 return node;
@@ -172,12 +160,11 @@ Texture* gfx_load_texture(Gfx* gfx, const LoadTextureCmd* cmd) {
172 RenderBackend* render_backend = gfx_get_render_backend(gfx); 160 RenderBackend* render_backend = gfx_get_render_backend(gfx);
173 Texture* texture = gfx_texture_load(render_backend, cmd); 161 Texture* texture = gfx_texture_load(render_backend, cmd);
174 if (texture) { 162 if (texture) {
175 insert_into_cache( 163 *(Asset*)mempool_alloc(&cache->assets) = (Asset){
176 cache, &(Asset){ 164 .type = TextureAsset,
177 .type = TextureAsset, 165 .hash = hash,
178 .hash = hash, 166 .data = texture,
179 .data = texture, 167 };
180 });
181 } 168 }
182 return texture; 169 return texture;
183} 170}
diff --git a/gfx/src/gfx_assert.h b/gfx/src/gfx_assert.h
new file mode 100644
index 0000000..f4b3aa5
--- /dev/null
+++ b/gfx/src/gfx_assert.h
@@ -0,0 +1,5 @@
1#pragma once
2
3#include <log/log.h>
4
5#include <cassert.h> // Include after log to use log's LOGE().
diff --git a/gfx/src/render/buffer.c b/gfx/src/render/buffer.c
index 55c68cc..28877bb 100644
--- a/gfx/src/render/buffer.c
+++ b/gfx/src/render/buffer.c
@@ -1,6 +1,7 @@
1#include "buffer.h" 1#include "buffer.h"
2 2
3#include <gfx/render_backend.h> 3#include <gfx/render_backend.h>
4#include <gfx_assert.h>
4 5
5#include <math/vec2.h> 6#include <math/vec2.h>
6#include <math/vec3.h> 7#include <math/vec3.h>
@@ -18,7 +19,7 @@ static GLenum get_buffer_usage(BufferUsage usage) {
18 case BufferDynamic: 19 case BufferDynamic:
19 return GL_DYNAMIC_DRAW; 20 return GL_DYNAMIC_DRAW;
20 } 21 }
21 assert(false); 22 FAIL("Unhandled buffer usage");
22 return GL_STATIC_DRAW; 23 return GL_STATIC_DRAW;
23} 24}
24 25
@@ -39,21 +40,24 @@ size_t gfx_get_buffer_type_size_bytes(BufferType type) {
39 case BufferU16: 40 case BufferU16:
40 return sizeof(uint16_t); 41 return sizeof(uint16_t);
41 } 42 }
42 assert(false); 43 FAIL("Unhandled buffer type");
43 return 0; 44 return 0;
44} 45}
45 46
46bool gfx_init_buffer(Buffer* buffer, const BufferDesc* desc) { 47bool gfx_init_buffer(Buffer* buffer, const BufferDesc* desc) {
47 assert(buffer); 48 assert(buffer);
49
48 buffer->type = desc->type; 50 buffer->type = desc->type;
49 buffer->usage = desc->usage; 51 buffer->usage = desc->usage;
50 buffer->size_bytes = get_buffer_size_bytes(desc->type, &desc->data); 52 buffer->size_bytes = get_buffer_size_bytes(desc->type, &desc->data);
51 const GLenum usage = get_buffer_usage(desc->usage); 53 const GLenum usage = get_buffer_usage(desc->usage);
54
52 glGenBuffers(1, &buffer->vbo); 55 glGenBuffers(1, &buffer->vbo);
53 glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo); 56 glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo);
54 glBufferData(GL_ARRAY_BUFFER, buffer->size_bytes, desc->data.data, usage); 57 glBufferData(GL_ARRAY_BUFFER, buffer->size_bytes, desc->data.data, usage);
55 glBindBuffer(GL_ARRAY_BUFFER, 0); 58 glBindBuffer(GL_ARRAY_BUFFER, 0);
56 ASSERT_GL; 59 ASSERT_GL;
60
57 return true; 61 return true;
58} 62}
59 63
diff --git a/gfx/src/render/framebuffer.c b/gfx/src/render/framebuffer.c
index 84ade4a..2ea2165 100644
--- a/gfx/src/render/framebuffer.c
+++ b/gfx/src/render/framebuffer.c
@@ -3,9 +3,9 @@
3#include "renderbuffer.h" 3#include "renderbuffer.h"
4#include "texture.h" 4#include "texture.h"
5 5
6#include <error.h> 6#include <gfx_assert.h>
7 7
8#include <assert.h> 8#include <error.h>
9 9
10static void framebuffer_attach_colour( 10static void framebuffer_attach_colour(
11 FrameBuffer* framebuffer, const FrameBufferAttachment* attachment) { 11 FrameBuffer* framebuffer, const FrameBufferAttachment* attachment) {
diff --git a/gfx/src/render/geometry.c b/gfx/src/render/geometry.c
index 44bfd04..8974387 100644
--- a/gfx/src/render/geometry.c
+++ b/gfx/src/render/geometry.c
@@ -3,6 +3,8 @@
3#include "buffer.h" 3#include "buffer.h"
4#include "constants.h" 4#include "constants.h"
5 5
6#include <gfx_assert.h>
7
6#include <math/vec2.h> 8#include <math/vec2.h>
7#include <math/vec3.h> 9#include <math/vec3.h>
8 10
@@ -20,10 +22,9 @@ static GLenum primitive_type_to_gl(PrimitiveType type) {
20 return GL_TRIANGLE_FAN; 22 return GL_TRIANGLE_FAN;
21 case TriangleStrip: 23 case TriangleStrip:
22 return GL_TRIANGLE_STRIP; 24 return GL_TRIANGLE_STRIP;
23 default:
24 LOGE("primitive_type_to_gl(): missing case");
25 return GL_INVALID_ENUM;
26 } 25 }
26 FAIL("primitive_type_to_gl(): missing case");
27 return GL_INVALID_ENUM;
27} 28}
28 29
29/// Create a typed buffer for the buffer view if the view does not already point 30/// Create a typed buffer for the buffer view if the view does not already point
@@ -300,7 +301,7 @@ void gfx_update_geometry(Geometry* geometry, const GeometryDesc* desc) {
300 } 301 }
301 // TODO: more 302 // TODO: more
302 else { 303 else {
303 assert(false && "TODO: gfx_update_geometry() - handle other buffer types"); 304 FAIL("TODO: gfx_update_geometry() - handle other buffer types");
304 } 305 }
305 306
306 if (desc->num_verts != 0) { 307 if (desc->num_verts != 0) {
diff --git a/gfx/src/render/render_backend.c b/gfx/src/render/render_backend.c
index defc164..4e783f8 100644
--- a/gfx/src/render/render_backend.c
+++ b/gfx/src/render/render_backend.c
@@ -2,7 +2,6 @@
2 2
3#include "gl_util.h" 3#include "gl_util.h"
4 4
5#include <GL/gl.h>
6// #include <log/log.h> 5// #include <log/log.h>
7 6
8#include <assert.h> 7#include <assert.h>
@@ -138,10 +137,8 @@ void gfx_set_polygon_offset(
138Buffer* gfx_make_buffer(RenderBackend* render_backend, const BufferDesc* desc) { 137Buffer* gfx_make_buffer(RenderBackend* render_backend, const BufferDesc* desc) {
139 assert(render_backend); 138 assert(render_backend);
140 assert(desc); 139 assert(desc);
140
141 Buffer* buffer = mempool_alloc(&render_backend->buffers); 141 Buffer* buffer = mempool_alloc(&render_backend->buffers);
142 if (!buffer) {
143 return 0;
144 }
145 if (!gfx_init_buffer(buffer, desc)) { 142 if (!gfx_init_buffer(buffer, desc)) {
146 mempool_free(&render_backend->buffers, &buffer); 143 mempool_free(&render_backend->buffers, &buffer);
147 return 0; 144 return 0;
@@ -152,8 +149,10 @@ Buffer* gfx_make_buffer(RenderBackend* render_backend, const BufferDesc* desc) {
152void gfx_destroy_buffer(RenderBackend* render_backend, Buffer** buffer) { 149void gfx_destroy_buffer(RenderBackend* render_backend, Buffer** buffer) {
153 assert(render_backend); 150 assert(render_backend);
154 assert(buffer); 151 assert(buffer);
155 gfx_del_buffer(*buffer); 152 if (*buffer) {
156 mempool_free(&render_backend->buffers, buffer); 153 gfx_del_buffer(*buffer);
154 mempool_free(&render_backend->buffers, buffer);
155 }
157} 156}
158 157
159// ----------------------------------------------------------------------------- 158// -----------------------------------------------------------------------------
@@ -164,10 +163,8 @@ Geometry* gfx_make_geometry(
164 RenderBackend* render_backend, const GeometryDesc* desc) { 163 RenderBackend* render_backend, const GeometryDesc* desc) {
165 assert(render_backend); 164 assert(render_backend);
166 assert(desc); 165 assert(desc);
166
167 Geometry* geometry = mempool_alloc(&render_backend->geometries); 167 Geometry* geometry = mempool_alloc(&render_backend->geometries);
168 if (!geometry) {
169 return 0;
170 }
171 if (!gfx_init_geometry(geometry, render_backend, desc)) { 168 if (!gfx_init_geometry(geometry, render_backend, desc)) {
172 mempool_free(&render_backend->geometries, &geometry); 169 mempool_free(&render_backend->geometries, &geometry);
173 return 0; 170 return 0;
@@ -178,8 +175,11 @@ Geometry* gfx_make_geometry(
178void gfx_destroy_geometry(RenderBackend* render_backend, Geometry** geometry) { 175void gfx_destroy_geometry(RenderBackend* render_backend, Geometry** geometry) {
179 assert(render_backend); 176 assert(render_backend);
180 assert(geometry); 177 assert(geometry);
181 gfx_del_geometry(*geometry); 178
182 mempool_free(&render_backend->geometries, geometry); 179 if (*geometry) {
180 gfx_del_geometry(*geometry);
181 mempool_free(&render_backend->geometries, geometry);
182 }
183} 183}
184 184
185// ----------------------------------------------------------------------------- 185// -----------------------------------------------------------------------------
@@ -190,10 +190,8 @@ Texture* gfx_make_texture(
190 RenderBackend* render_backend, const TextureDesc* desc) { 190 RenderBackend* render_backend, const TextureDesc* desc) {
191 assert(render_backend); 191 assert(render_backend);
192 assert(desc); 192 assert(desc);
193
193 Texture* texture = mempool_alloc(&render_backend->textures); 194 Texture* texture = mempool_alloc(&render_backend->textures);
194 if (!texture) {
195 return 0;
196 }
197 if (!gfx_init_texture(texture, desc)) { 195 if (!gfx_init_texture(texture, desc)) {
198 mempool_free(&render_backend->textures, &texture); 196 mempool_free(&render_backend->textures, &texture);
199 return 0; 197 return 0;
@@ -205,8 +203,11 @@ void gfx_destroy_texture(RenderBackend* render_backend, Texture** texture) {
205 assert(render_backend); 203 assert(render_backend);
206 assert(texture); 204 assert(texture);
207 assert(*texture); 205 assert(*texture);
208 gfx_del_texture(*texture); 206
209 mempool_free(&render_backend->textures, texture); 207 if (*texture) {
208 gfx_del_texture(*texture);
209 mempool_free(&render_backend->textures, texture);
210 }
210} 211}
211 212
212// ----------------------------------------------------------------------------- 213// -----------------------------------------------------------------------------
@@ -217,10 +218,8 @@ RenderBuffer* gfx_make_renderbuffer(
217 RenderBackend* render_backend, const RenderBufferDesc* desc) { 218 RenderBackend* render_backend, const RenderBufferDesc* desc) {
218 assert(render_backend); 219 assert(render_backend);
219 assert(desc); 220 assert(desc);
221
220 RenderBuffer* renderbuffer = mempool_alloc(&render_backend->renderbuffers); 222 RenderBuffer* renderbuffer = mempool_alloc(&render_backend->renderbuffers);
221 if (!renderbuffer) {
222 return 0;
223 }
224 if (!gfx_init_renderbuffer(renderbuffer, desc)) { 223 if (!gfx_init_renderbuffer(renderbuffer, desc)) {
225 mempool_free(&render_backend->renderbuffers, &renderbuffer); 224 mempool_free(&render_backend->renderbuffers, &renderbuffer);
226 } 225 }
@@ -232,8 +231,11 @@ void gfx_destroy_renderbuffer(
232 assert(render_backend); 231 assert(render_backend);
233 assert(renderbuffer); 232 assert(renderbuffer);
234 assert(*renderbuffer); 233 assert(*renderbuffer);
235 gfx_del_renderbuffer(*renderbuffer); 234
236 mempool_free(&render_backend->renderbuffers, renderbuffer); 235 if (*renderbuffer) {
236 gfx_del_renderbuffer(*renderbuffer);
237 mempool_free(&render_backend->renderbuffers, renderbuffer);
238 }
237} 239}
238 240
239// ----------------------------------------------------------------------------- 241// -----------------------------------------------------------------------------
@@ -244,10 +246,8 @@ FrameBuffer* gfx_make_framebuffer(
244 RenderBackend* render_backend, const FrameBufferDesc* desc) { 246 RenderBackend* render_backend, const FrameBufferDesc* desc) {
245 assert(render_backend); 247 assert(render_backend);
246 assert(desc); 248 assert(desc);
249
247 FrameBuffer* framebuffer = mempool_alloc(&render_backend->framebuffers); 250 FrameBuffer* framebuffer = mempool_alloc(&render_backend->framebuffers);
248 if (!framebuffer) {
249 return 0;
250 }
251 if (!gfx_init_framebuffer(framebuffer, desc)) { 251 if (!gfx_init_framebuffer(framebuffer, desc)) {
252 mempool_free(&render_backend->framebuffers, &framebuffer); 252 mempool_free(&render_backend->framebuffers, &framebuffer);
253 return 0; 253 return 0;
@@ -260,8 +260,11 @@ void gfx_destroy_framebuffer(
260 assert(render_backend); 260 assert(render_backend);
261 assert(framebuffer); 261 assert(framebuffer);
262 assert(*framebuffer); 262 assert(*framebuffer);
263 gfx_del_framebuffer(*framebuffer); 263
264 mempool_free(&render_backend->framebuffers, framebuffer); 264 if (*framebuffer) {
265 gfx_del_framebuffer(*framebuffer);
266 mempool_free(&render_backend->framebuffers, framebuffer);
267 }
265} 268}
266 269
267// ----------------------------------------------------------------------------- 270// -----------------------------------------------------------------------------
@@ -340,7 +343,7 @@ Shader* gfx_make_shader(RenderBackend* render_backend, const ShaderDesc* desc) {
340 const uint64_t hash = hash_shader_desc(desc); 343 const uint64_t hash = hash_shader_desc(desc);
341 Shader* shader = find_cached_shader(cache, hash); 344 Shader* shader = find_cached_shader(cache, hash);
342 if (shader) { 345 if (shader) {
343 // LOGD("Found cached shader with hash %lx", hash); 346 // LOGD("Found cached shader with hash [%lx]", hash);
344 return shader; 347 return shader;
345 } 348 }
346 349
@@ -353,25 +356,25 @@ Shader* gfx_make_shader(RenderBackend* render_backend, const ShaderDesc* desc) {
353 return 0; 356 return 0;
354 } 357 }
355 ShaderCacheEntry* entry = mempool_alloc(cache); 358 ShaderCacheEntry* entry = mempool_alloc(cache);
356 assert(entry); 359 *entry = (ShaderCacheEntry){.hash = hash, .shader = shader};
357 *entry = (ShaderCacheEntry){.hash = hash, .shader = shader}; 360 // LOGD("Added shader with hash [%lx] to cache", hash);
358 // LOGD("Added shader with hash %lx to cache", hash);
359 return shader; 361 return shader;
360} 362}
361 363
362void gfx_destroy_shader(RenderBackend* render_backend, Shader** shader) { 364void gfx_destroy_shader(RenderBackend* render_backend, Shader** shader) {
363 assert(render_backend); 365 assert(render_backend);
364 assert(shader); 366 assert(shader);
365 assert(*shader);
366 367
367 // Remove the shader from the cache. 368 if (*shader) {
368 ShaderCache* cache = &render_backend->shader_cache; 369 // Remove the shader from the cache.
369 ShaderCacheEntry* entry = find_shader_cache_entry(cache, *shader); 370 ShaderCache* cache = &render_backend->shader_cache;
370 assert(entry); // Must be there, shaders can't go untracked. 371 ShaderCacheEntry* entry = find_shader_cache_entry(cache, *shader);
371 mempool_free(cache, &entry); 372 assert(entry); // Must be there, shaders can't go untracked.
373 mempool_free(cache, &entry);
372 374
373 gfx_del_shader(*shader); 375 gfx_del_shader(*shader);
374 mempool_free(&render_backend->shaders, shader); 376 mempool_free(&render_backend->shaders, shader);
377 }
375} 378}
376 379
377ShaderProgram* gfx_make_shader_program( 380ShaderProgram* gfx_make_shader_program(
@@ -384,22 +387,18 @@ ShaderProgram* gfx_make_shader_program(
384 const uint64_t hash = hash_program_desc(desc); 387 const uint64_t hash = hash_program_desc(desc);
385 ShaderProgram* prog = find_cached_program(cache, hash); 388 ShaderProgram* prog = find_cached_program(cache, hash);
386 if (prog) { 389 if (prog) {
387 // LOGD("Found cached shader program with hash %lx", hash); 390 // LOGD("Found cached shader program with hash [%lx]", hash);
388 return prog; 391 return prog;
389 } 392 }
390 393
391 prog = mempool_alloc(&render_backend->shader_programs); 394 prog = mempool_alloc(&render_backend->shader_programs);
392 if (!prog) {
393 return 0;
394 }
395 if (!gfx_build_shader_program(prog, desc)) { 395 if (!gfx_build_shader_program(prog, desc)) {
396 mempool_free(&render_backend->shader_programs, &prog); 396 mempool_free(&render_backend->shader_programs, &prog);
397 return 0; 397 return 0;
398 } 398 }
399 ShaderProgramCacheEntry* entry = mempool_alloc(cache); 399 ShaderProgramCacheEntry* entry = mempool_alloc(cache);
400 assert(entry);
401 *entry = (ShaderProgramCacheEntry){.hash = hash, .program = prog}; 400 *entry = (ShaderProgramCacheEntry){.hash = hash, .program = prog};
402 // LOGD("Added shader program with hash %lx to cache", hash); 401 // LOGD("Added shader program with hash [%lx] to cache", hash);
403 return prog; 402 return prog;
404} 403}
405 404
@@ -407,14 +406,14 @@ void gfx_destroy_shader_program(
407 RenderBackend* render_backend, ShaderProgram** prog) { 406 RenderBackend* render_backend, ShaderProgram** prog) {
408 assert(render_backend); 407 assert(render_backend);
409 assert(prog); 408 assert(prog);
410 assert(*prog); 409 if (*prog) {
411 410 // Remove the shader program from the cache.
412 // Remove the shader program from the cache. 411 ProgramCache* cache = &render_backend->program_cache;
413 ProgramCache* cache = &render_backend->program_cache; 412 ShaderProgramCacheEntry* entry = find_program_cache_entry(cache, *prog);
414 ShaderProgramCacheEntry* entry = find_program_cache_entry(cache, *prog); 413 assert(entry); // Must be there, shaders can't go untracked.
415 assert(entry); // Must be there, shaders can't go untracked. 414 mempool_free(cache, &entry);
416 mempool_free(cache, &entry); 415
417 416 gfx_del_shader_program(*prog);
418 gfx_del_shader_program(*prog); 417 mempool_free(&render_backend->shader_programs, prog);
419 mempool_free(&render_backend->shader_programs, prog); 418 }
420} 419}
diff --git a/gfx/src/render/renderbuffer.c b/gfx/src/render/renderbuffer.c
index a2eae52..23f9524 100644
--- a/gfx/src/render/renderbuffer.c
+++ b/gfx/src/render/renderbuffer.c
@@ -27,6 +27,7 @@ bool gfx_init_renderbuffer(
27 27
28void gfx_del_renderbuffer(RenderBuffer* renderbuffer) { 28void gfx_del_renderbuffer(RenderBuffer* renderbuffer) {
29 assert(renderbuffer); 29 assert(renderbuffer);
30
30 if (renderbuffer->id) { 31 if (renderbuffer->id) {
31 glDeleteRenderbuffers(1, &renderbuffer->id); 32 glDeleteRenderbuffers(1, &renderbuffer->id);
32 renderbuffer->id = 0; 33 renderbuffer->id = 0;
diff --git a/gfx/src/render/shader.c b/gfx/src/render/shader.c
index d4778a2..af2f89f 100644
--- a/gfx/src/render/shader.c
+++ b/gfx/src/render/shader.c
@@ -1,11 +1,11 @@
1#include "shader.h" 1#include "shader.h"
2 2
3#include "gl_util.h" 3#include "gl_util.h"
4#include <gfx_assert.h>
4 5
5#include <cstring.h> 6#include <cstring.h>
6#include <log/log.h> 7#include <log/log.h>
7 8
8#include <assert.h>
9#include <stdlib.h> 9#include <stdlib.h>
10#include <string.h> 10#include <string.h>
11 11
@@ -15,10 +15,9 @@ static GLenum shader_type_to_gl(ShaderType type) {
15 return GL_VERTEX_SHADER; 15 return GL_VERTEX_SHADER;
16 case FragmentShader: 16 case FragmentShader:
17 return GL_FRAGMENT_SHADER; 17 return GL_FRAGMENT_SHADER;
18 default:
19 LOGE("shader_type_to_gl(): missing case");
20 return GL_INVALID_ENUM;
21 } 18 }
19 FAIL("shader_type_to_gl(): missing case");
20 return GL_INVALID_ENUM;
22} 21}
23 22
24static lstring make_defines_string(const ShaderDesc* desc) { 23static lstring make_defines_string(const ShaderDesc* desc) {
@@ -84,6 +83,7 @@ bool gfx_compile_shader(Shader* shader, const ShaderDesc* desc) {
84 83
85void gfx_del_shader(Shader* shader) { 84void gfx_del_shader(Shader* shader) {
86 assert(shader); 85 assert(shader);
86
87 if (shader->id) { 87 if (shader->id) {
88 glDeleteShader(shader->id); 88 glDeleteShader(shader->id);
89 shader->id = 0; 89 shader->id = 0;
diff --git a/gfx/src/render/shader_program.c b/gfx/src/render/shader_program.c
index d80ee4f..3cbe48d 100644
--- a/gfx/src/render/shader_program.c
+++ b/gfx/src/render/shader_program.c
@@ -3,10 +3,10 @@
3#include "gl_util.h" 3#include "gl_util.h"
4#include "shader.h" 4#include "shader.h"
5#include "texture.h" 5#include "texture.h"
6#include <gfx_assert.h>
6 7
7#include <log/log.h> 8#include <log/log.h>
8 9
9#include <assert.h>
10#include <stdlib.h> 10#include <stdlib.h>
11#include <string.h> 11#include <string.h>
12 12
@@ -45,12 +45,14 @@ bool gfx_build_shader_program(
45 ShaderProgram* prog, const ShaderProgramDesc* desc) { 45 ShaderProgram* prog, const ShaderProgramDesc* desc) {
46 assert(prog); 46 assert(prog);
47 assert(desc); 47 assert(desc);
48
48 prog->id = create_program(desc->vertex_shader->id, desc->fragment_shader->id); 49 prog->id = create_program(desc->vertex_shader->id, desc->fragment_shader->id);
49 return prog->id != 0; 50 return prog->id != 0;
50} 51}
51 52
52void gfx_del_shader_program(ShaderProgram* prog) { 53void gfx_del_shader_program(ShaderProgram* prog) {
53 assert(prog); 54 assert(prog);
55
54 if (prog->id) { 56 if (prog->id) {
55 glDeleteProgram(prog->id); 57 glDeleteProgram(prog->id);
56 prog->id = 0; 58 prog->id = 0;
@@ -75,6 +77,7 @@ static void set_texture_uniform(
75 assert(prog != 0); 77 assert(prog != 0);
76 assert(name); 78 assert(name);
77 assert(texture); 79 assert(texture);
80
78 const GLint location = glGetUniformLocation(prog, name); 81 const GLint location = glGetUniformLocation(prog, name);
79 if (location >= 0) { 82 if (location >= 0) {
80 glActiveTexture(GL_TEXTURE0 + texture_unit); 83 glActiveTexture(GL_TEXTURE0 + texture_unit);
@@ -88,6 +91,7 @@ static void set_mat4_uniform(
88 assert(prog != 0); 91 assert(prog != 0);
89 assert(name); 92 assert(name);
90 assert(mats); 93 assert(mats);
94
91 const GLint location = glGetUniformLocation(prog, name); 95 const GLint location = glGetUniformLocation(prog, name);
92 if (location >= 0) { 96 if (location >= 0) {
93 glUniformMatrix4fv(location, count, GL_FALSE, (const float*)mats); 97 glUniformMatrix4fv(location, count, GL_FALSE, (const float*)mats);
@@ -97,6 +101,7 @@ static void set_mat4_uniform(
97static void set_vec3_uniform(GLuint prog, const char* name, vec3 value) { 101static void set_vec3_uniform(GLuint prog, const char* name, vec3 value) {
98 assert(prog != 0); 102 assert(prog != 0);
99 assert(name); 103 assert(name);
104
100 const GLint location = glGetUniformLocation(prog, name); 105 const GLint location = glGetUniformLocation(prog, name);
101 if (location >= 0) { 106 if (location >= 0) {
102 glUniform3f(location, value.x, value.y, value.z); 107 glUniform3f(location, value.x, value.y, value.z);
@@ -106,6 +111,7 @@ static void set_vec3_uniform(GLuint prog, const char* name, vec3 value) {
106static void set_vec4_uniform(GLuint prog, const char* name, vec4 value) { 111static void set_vec4_uniform(GLuint prog, const char* name, vec4 value) {
107 assert(prog != 0); 112 assert(prog != 0);
108 assert(name); 113 assert(name);
114
109 const GLint location = glGetUniformLocation(prog, name); 115 const GLint location = glGetUniformLocation(prog, name);
110 if (location >= 0) { 116 if (location >= 0) {
111 glUniform4f(location, value.x, value.y, value.z, value.w); 117 glUniform4f(location, value.x, value.y, value.z, value.w);
@@ -115,6 +121,7 @@ static void set_vec4_uniform(GLuint prog, const char* name, vec4 value) {
115static void set_float_uniform(GLuint prog, const char* name, float value) { 121static void set_float_uniform(GLuint prog, const char* name, float value) {
116 assert(prog != 0); 122 assert(prog != 0);
117 assert(name); 123 assert(name);
124
118 const GLint location = glGetUniformLocation(prog, name); 125 const GLint location = glGetUniformLocation(prog, name);
119 if (location >= 0) { 126 if (location >= 0) {
120 glUniform1f(location, value); 127 glUniform1f(location, value);
@@ -123,6 +130,7 @@ static void set_float_uniform(GLuint prog, const char* name, float value) {
123 130
124void gfx_apply_uniforms(const ShaderProgram* prog) { 131void gfx_apply_uniforms(const ShaderProgram* prog) {
125 assert(prog); 132 assert(prog);
133
126 int next_texture_unit = 0; 134 int next_texture_unit = 0;
127 for (int i = 0; i < prog->num_uniforms; ++i) { 135 for (int i = 0; i < prog->num_uniforms; ++i) {
128 const ShaderUniform* uniform = &prog->uniforms[i]; 136 const ShaderUniform* uniform = &prog->uniforms[i];
@@ -160,6 +168,7 @@ static ShaderUniform* get_or_allocate_uniform(
160 ShaderProgram* prog, const char* name) { 168 ShaderProgram* prog, const char* name) {
161 assert(prog); 169 assert(prog);
162 assert(name); 170 assert(name);
171
163 // First search for the uniform in the list. 172 // First search for the uniform in the list.
164 for (int i = 0; i < prog->num_uniforms; ++i) { 173 for (int i = 0; i < prog->num_uniforms; ++i) {
165 ShaderUniform* uniform = &prog->uniforms[i]; 174 ShaderUniform* uniform = &prog->uniforms[i];
@@ -167,11 +176,11 @@ static ShaderUniform* get_or_allocate_uniform(
167 return uniform; 176 return uniform;
168 } 177 }
169 } 178 }
179
170 // Create the uniform if it does not exist. 180 // Create the uniform if it does not exist.
171 if (prog->num_uniforms == GFX_MAX_UNIFORMS_PER_SHADER) { 181 if (prog->num_uniforms == GFX_MAX_UNIFORMS_PER_SHADER) {
172 LOGE("Exceeded the maximum number of uniforms per shader. Please increase " 182 FAIL("Exceeded the maximum number of uniforms per shader. Please increase "
173 "this value."); 183 "this value.");
174 assert(false);
175 return 0; 184 return 0;
176 } 185 }
177 ShaderUniform* uniform = &prog->uniforms[prog->num_uniforms]; 186 ShaderUniform* uniform = &prog->uniforms[prog->num_uniforms];
@@ -187,6 +196,7 @@ void gfx_set_texture_uniform(
187 assert(prog); 196 assert(prog);
188 assert(name); 197 assert(name);
189 assert(texture); 198 assert(texture);
199
190 const GLint location = glGetUniformLocation(prog->id, name); 200 const GLint location = glGetUniformLocation(prog->id, name);
191 if (location < 0) { 201 if (location < 0) {
192 return; 202 return;
@@ -203,6 +213,7 @@ void gfx_set_mat4_uniform(
203 assert(prog); 213 assert(prog);
204 assert(name); 214 assert(name);
205 assert(mat); 215 assert(mat);
216
206 const GLint location = glGetUniformLocation(prog->id, name); 217 const GLint location = glGetUniformLocation(prog->id, name);
207 if (location < 0) { 218 if (location < 0) {
208 return; 219 return;
@@ -217,6 +228,7 @@ void gfx_set_mat4_uniform(
217void gfx_set_vec3_uniform(ShaderProgram* prog, const char* name, vec3 value) { 228void gfx_set_vec3_uniform(ShaderProgram* prog, const char* name, vec3 value) {
218 assert(prog); 229 assert(prog);
219 assert(name); 230 assert(name);
231
220 const GLint location = glGetUniformLocation(prog->id, name); 232 const GLint location = glGetUniformLocation(prog->id, name);
221 if (location < 0) { 233 if (location < 0) {
222 return; 234 return;
@@ -231,6 +243,7 @@ void gfx_set_vec3_uniform(ShaderProgram* prog, const char* name, vec3 value) {
231void gfx_set_vec4_uniform(ShaderProgram* prog, const char* name, vec4 value) { 243void gfx_set_vec4_uniform(ShaderProgram* prog, const char* name, vec4 value) {
232 assert(prog); 244 assert(prog);
233 assert(name); 245 assert(name);
246
234 const GLint location = glGetUniformLocation(prog->id, name); 247 const GLint location = glGetUniformLocation(prog->id, name);
235 if (location < 0) { 248 if (location < 0) {
236 return; 249 return;
@@ -245,6 +258,7 @@ void gfx_set_vec4_uniform(ShaderProgram* prog, const char* name, vec4 value) {
245void gfx_set_float_uniform(ShaderProgram* prog, const char* name, float value) { 258void gfx_set_float_uniform(ShaderProgram* prog, const char* name, float value) {
246 assert(prog); 259 assert(prog);
247 assert(name); 260 assert(name);
261
248 // No need to store the uniform on our side if it does not exist in the 262 // No need to store the uniform on our side if it does not exist in the
249 // program. 263 // program.
250 const GLint location = glGetUniformLocation(prog->id, name); 264 const GLint location = glGetUniformLocation(prog->id, name);
@@ -263,6 +277,7 @@ void gfx_set_mat4_array_uniform(
263 assert(prog); 277 assert(prog);
264 assert(name); 278 assert(name);
265 assert(mats); 279 assert(mats);
280
266 const GLint location = glGetUniformLocation(prog->id, name); 281 const GLint location = glGetUniformLocation(prog->id, name);
267 if (location < 0) { 282 if (location < 0) {
268 return; 283 return;
diff --git a/gfx/src/render/texture.c b/gfx/src/render/texture.c
index 489f7a2..fd1d4dd 100644
--- a/gfx/src/render/texture.c
+++ b/gfx/src/render/texture.c
@@ -1,9 +1,10 @@
1#include "texture.h" 1#include "texture.h"
2 2
3#include <gfx_assert.h>
4
3#include <error.h> 5#include <error.h>
4#include <math/defs.h> 6#include <math/defs.h>
5 7
6#include <assert.h>
7#include <stdbool.h> 8#include <stdbool.h>
8 9
9bool gfx_init_texture(Texture* texture, const TextureDesc* desc) { 10bool gfx_init_texture(Texture* texture, const TextureDesc* desc) {
@@ -32,7 +33,7 @@ bool gfx_init_texture(Texture* texture, const TextureDesc* desc) {
32 texture->target, levels, internal_format, desc->width, desc->height); 33 texture->target, levels, internal_format, desc->width, desc->height);
33 break; 34 break;
34 default: 35 default:
35 assert(false && "Unhandled texture dimension"); 36 FAIL("Unhandled texture dimension");
36 gfx_del_texture(texture); 37 gfx_del_texture(texture);
37 return false; 38 return false;
38 } 39 }
@@ -79,6 +80,8 @@ bool gfx_init_texture(Texture* texture, const TextureDesc* desc) {
79} 80}
80 81
81void gfx_del_texture(Texture* texture) { 82void gfx_del_texture(Texture* texture) {
83 assert(texture);
84
82 if (texture->id) { 85 if (texture->id) {
83 glDeleteTextures(1, &texture->id); 86 glDeleteTextures(1, &texture->id);
84 texture->id = 0; 87 texture->id = 0;
@@ -113,7 +116,7 @@ void gfx_update_texture(Texture* texture, const TextureDataDesc* desc) {
113 } 116 }
114 break; 117 break;
115 default: 118 default:
116 assert(false && "Unhandled texture dimension"); 119 FAIL("Unhandled texture dimension");
117 break; 120 break;
118 } 121 }
119 122
@@ -127,7 +130,7 @@ GLenum to_GL_dimension(TextureDimension dim) {
127 case TextureCubeMap: 130 case TextureCubeMap:
128 return GL_TEXTURE_CUBE_MAP; 131 return GL_TEXTURE_CUBE_MAP;
129 default: 132 default:
130 assert(false && "Unhandled TextureDimension"); 133 FAIL("Unhandled TextureDimension");
131 return GL_INVALID_ENUM; 134 return GL_INVALID_ENUM;
132 } 135 }
133} 136}
@@ -151,7 +154,7 @@ GLenum to_GL_internal_format(TextureFormat format) {
151 case TextureSRGBA8: 154 case TextureSRGBA8:
152 return GL_SRGB8_ALPHA8; 155 return GL_SRGB8_ALPHA8;
153 default: 156 default:
154 assert(false && "Unhandled TextureFormat"); 157 FAIL("Unhandled TextureFormat");
155 return GL_INVALID_ENUM; 158 return GL_INVALID_ENUM;
156 } 159 }
157} 160}
@@ -171,7 +174,7 @@ GLenum to_GL_format(TextureFormat format) {
171 case TextureSRGBA8: 174 case TextureSRGBA8:
172 return GL_RGBA; 175 return GL_RGBA;
173 default: 176 default:
174 assert(false && "Unhandled TextureFormat"); 177 FAIL("Unhandled TextureFormat");
175 return GL_INVALID_ENUM; 178 return GL_INVALID_ENUM;
176 } 179 }
177} 180}
@@ -189,7 +192,7 @@ GLenum to_GL_type(TextureFormat format) {
189 case TextureSRGBA8: 192 case TextureSRGBA8:
190 return GL_UNSIGNED_BYTE; 193 return GL_UNSIGNED_BYTE;
191 default: 194 default:
192 assert(false && "Unhandled TextureFormat"); 195 FAIL("Unhandled TextureFormat");
193 return GL_INVALID_ENUM; 196 return GL_INVALID_ENUM;
194 } 197 }
195} 198}
@@ -209,7 +212,7 @@ GLenum to_GL_cubemap_face(CubemapFace face) {
209 case CubemapFaceNegZ: 212 case CubemapFaceNegZ:
210 return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; 213 return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
211 default: 214 default:
212 assert(false && "Unhandled CubemapFace"); 215 FAIL("Unhandled CubemapFace");
213 return GL_INVALID_ENUM; 216 return GL_INVALID_ENUM;
214 } 217 }
215} 218}
diff --git a/gfx/src/scene/animation.c b/gfx/src/scene/animation.c
index 8d8178e..459e864 100644
--- a/gfx/src/scene/animation.c
+++ b/gfx/src/scene/animation.c
@@ -13,8 +13,7 @@ Joint* gfx_make_joint(const JointDesc* desc) {
13 // The joint matrix needs to be initialized so that meshes look right even if 13 // The joint matrix needs to be initialized so that meshes look right even if
14 // no animation is played. Initializing joint matrices to the identity makes 14 // no animation is played. Initializing joint matrices to the identity makes
15 // meshes appear in their bind pose. 15 // meshes appear in their bind pose.
16 Joint* joint = mem_alloc_joint(); 16 Joint* joint = mem_alloc_joint();
17 assert(joint);
18 joint->inv_bind_matrix = desc->inv_bind_matrix; 17 joint->inv_bind_matrix = desc->inv_bind_matrix;
19 joint->joint_matrix = mat4_id(); 18 joint->joint_matrix = mat4_id();
20 return joint; 19 return joint;
@@ -22,20 +21,20 @@ Joint* gfx_make_joint(const JointDesc* desc) {
22 21
23void gfx_destroy_joint(Joint** joint) { 22void gfx_destroy_joint(Joint** joint) {
24 assert(joint); 23 assert(joint);
25 assert(*joint);
26 24
27 if ((*joint)->parent.val) { 25 if (*joint) {
28 gfx_del_node((*joint)->parent); 26 if ((*joint)->parent.val) {
27 gfx_del_node((*joint)->parent);
28 }
29 mem_free_joint(joint);
29 } 30 }
30 mem_free_joint(joint);
31} 31}
32 32
33static Skeleton* make_skeleton(const SkeletonDesc* desc) { 33static Skeleton* make_skeleton(const SkeletonDesc* desc) {
34 assert(desc); 34 assert(desc);
35 assert(desc->num_joints < GFX_MAX_NUM_JOINTS); 35 assert(desc->num_joints < GFX_MAX_NUM_JOINTS);
36 36
37 Skeleton* skeleton = mem_alloc_skeleton(); 37 Skeleton* skeleton = mem_alloc_skeleton();
38 assert(skeleton);
39 skeleton->num_joints = desc->num_joints; 38 skeleton->num_joints = desc->num_joints;
40 for (size_t i = 0; i < desc->num_joints; ++i) { 39 for (size_t i = 0; i < desc->num_joints; ++i) {
41 skeleton->joints[i] = mem_get_node_index(desc->joints[i]); 40 skeleton->joints[i] = mem_get_node_index(desc->joints[i]);
@@ -47,8 +46,7 @@ static Animation* make_animation(const AnimationDesc* desc) {
47 assert(desc); 46 assert(desc);
48 assert(desc->num_channels < GFX_MAX_NUM_CHANNELS); 47 assert(desc->num_channels < GFX_MAX_NUM_CHANNELS);
49 48
50 Animation* animation = mem_alloc_animation(); 49 Animation* animation = mem_alloc_animation();
51 assert(animation);
52 animation->name = desc->name; 50 animation->name = desc->name;
53 animation->duration = 0; 51 animation->duration = 0;
54 animation->num_channels = desc->num_channels; 52 animation->num_channels = desc->num_channels;
@@ -86,9 +84,6 @@ Anima* gfx_make_anima(const AnimaDesc* desc) {
86 assert(desc); 84 assert(desc);
87 85
88 Anima* anima = mem_alloc_anima(); 86 Anima* anima = mem_alloc_anima();
89 if (!anima) {
90 return 0;
91 }
92 87
93 // Wire the skeletons in the same order they are given in the descriptor. 88 // Wire the skeletons in the same order they are given in the descriptor.
94 Skeleton* last_skeleton = 0; 89 Skeleton* last_skeleton = 0;
@@ -97,7 +92,6 @@ Anima* gfx_make_anima(const AnimaDesc* desc) {
97 // TODO: Here and everywhere else, I think it would simplify the code 92 // TODO: Here and everywhere else, I think it would simplify the code
98 // greatly to make mem_alloc_xyz() fail if the allocation fails. At that 93 // greatly to make mem_alloc_xyz() fail if the allocation fails. At that
99 // point the user should just bump their memory limits. 94 // point the user should just bump their memory limits.
100 assert(skeleton);
101 const skeleton_idx skeleton_index = mem_get_skeleton_index(skeleton); 95 const skeleton_idx skeleton_index = mem_get_skeleton_index(skeleton);
102 if (last_skeleton == 0) { 96 if (last_skeleton == 0) {
103 anima->skeleton = skeleton_index; 97 anima->skeleton = skeleton_index;
@@ -110,8 +104,7 @@ Anima* gfx_make_anima(const AnimaDesc* desc) {
110 // Wire the animations in the same order they are given in the descriptor. 104 // Wire the animations in the same order they are given in the descriptor.
111 Animation* last_animation = 0; 105 Animation* last_animation = 0;
112 for (size_t i = 0; i < desc->num_animations; ++i) { 106 for (size_t i = 0; i < desc->num_animations; ++i) {
113 Animation* animation = make_animation(&desc->animations[i]); 107 Animation* animation = make_animation(&desc->animations[i]);
114 assert(animation);
115 const animation_idx animation_index = mem_get_animation_index(animation); 108 const animation_idx animation_index = mem_get_animation_index(animation);
116 if (last_animation == 0) { 109 if (last_animation == 0) {
117 anima->animation = animation_index; 110 anima->animation = animation_index;
@@ -126,25 +119,26 @@ Anima* gfx_make_anima(const AnimaDesc* desc) {
126 119
127void gfx_destroy_anima(Anima** anima) { 120void gfx_destroy_anima(Anima** anima) {
128 assert(anima); 121 assert(anima);
129 assert(*anima);
130 122
131 for (skeleton_idx i = (*anima)->skeleton; i.val != 0;) { 123 if (*anima) {
132 Skeleton* skeleton = mem_get_skeleton(i); 124 for (skeleton_idx i = (*anima)->skeleton; i.val != 0;) {
133 i = skeleton->next; 125 Skeleton* skeleton = mem_get_skeleton(i);
134 mem_free_skeleton(&skeleton); 126 i = skeleton->next;
135 } 127 mem_free_skeleton(&skeleton);
128 }
136 129
137 for (animation_idx i = (*anima)->animation; i.val != 0;) { 130 for (animation_idx i = (*anima)->animation; i.val != 0;) {
138 Animation* animation = mem_get_animation(i); 131 Animation* animation = mem_get_animation(i);
139 i = animation->next; 132 i = animation->next;
140 mem_free_animation(&animation); 133 mem_free_animation(&animation);
141 } 134 }
142 135
143 if ((*anima)->parent.val) { 136 if ((*anima)->parent.val) {
144 gfx_del_node((*anima)->parent); 137 gfx_del_node((*anima)->parent);
145 } 138 }
146 139
147 mem_free_anima(anima); 140 mem_free_anima(anima);
141 }
148} 142}
149 143
150static Animation* find_animation(animation_idx index, const char* name) { 144static Animation* find_animation(animation_idx index, const char* name) {
@@ -152,7 +146,6 @@ static Animation* find_animation(animation_idx index, const char* name) {
152 146
153 while (index.val != 0) { 147 while (index.val != 0) {
154 Animation* animation = mem_get_animation(index); 148 Animation* animation = mem_get_animation(index);
155 assert(animation);
156 if (sstring_eq_cstr(animation->name, name)) { 149 if (sstring_eq_cstr(animation->name, name)) {
157 // LOGD( 150 // LOGD(
158 // "Found animation at index %u, %s - %s", index.val, 151 // "Found animation at index %u, %s - %s", index.val,
@@ -171,7 +164,7 @@ bool gfx_play_animation(Anima* anima, const AnimationPlaySettings* settings) {
171 assert(settings); 164 assert(settings);
172 165
173 // TODO: Should we animate at t=0 here to kickstart the animation? Otherwise 166 // TODO: Should we animate at t=0 here to kickstart the animation? Otherwise
174 // the client is forced to call gfx_update_animation() to do this. 167 // the client is forced to call gfx_update_animation() to do this.
175 Animation* animation = find_animation(anima->animation, settings->name); 168 Animation* animation = find_animation(anima->animation, settings->name);
176 if (!animation) { 169 if (!animation) {
177 return false; 170 return false;
@@ -188,6 +181,7 @@ static void find_keyframes(const Channel* channel, R t, int* prev, int* next) {
188 assert(channel); 181 assert(channel);
189 assert(prev); 182 assert(prev);
190 assert(next); 183 assert(next);
184
191 *prev = -1; 185 *prev = -1;
192 *next = 0; 186 *next = 0;
193 while (((*next + 1) < (int)channel->num_keyframes) && 187 while (((*next + 1) < (int)channel->num_keyframes) &&
@@ -275,7 +269,6 @@ static void animate_channel(const Channel* channel, R t) {
275 t = t > channel->keyframes[next].time ? channel->keyframes[next].time : t; 269 t = t > channel->keyframes[next].time ? channel->keyframes[next].time : t;
276 270
277 SceneNode* target = mem_get_node(channel->target); 271 SceneNode* target = mem_get_node(channel->target);
278 assert(target);
279 272
280 switch (channel->type) { 273 switch (channel->type) {
281 case RotationChannel: { 274 case RotationChannel: {
@@ -306,8 +299,7 @@ static void compute_joint_matrices_rec(
306 } 299 }
307 300
308 const SceneNode* node = mem_get_node(node_index); 301 const SceneNode* node = mem_get_node(node_index);
309 assert(node); 302 const mat4 global_joint_transform =
310 const mat4 global_joint_transform =
311 mat4_mul(parent_global_joint_transform, node->transform); 303 mat4_mul(parent_global_joint_transform, node->transform);
312 304
313 // For flexibility (glTF), we allow non-joint nodes between the root of the 305 // For flexibility (glTF), we allow non-joint nodes between the root of the
@@ -316,7 +308,6 @@ static void compute_joint_matrices_rec(
316 if (node->type == JointNode) { 308 if (node->type == JointNode) {
317 // Compute this node's joint matrix. 309 // Compute this node's joint matrix.
318 Joint* joint = mem_get_joint(node->joint); 310 Joint* joint = mem_get_joint(node->joint);
319 assert(joint);
320 311
321 joint->joint_matrix = mat4_mul( 312 joint->joint_matrix = mat4_mul(
322 *root_inv_global_transform, 313 *root_inv_global_transform,
@@ -328,8 +319,7 @@ static void compute_joint_matrices_rec(
328 while (child.val != 0) { 319 while (child.val != 0) {
329 compute_joint_matrices_rec( 320 compute_joint_matrices_rec(
330 child, global_joint_transform, root_inv_global_transform); 321 child, global_joint_transform, root_inv_global_transform);
331 node = mem_get_node(child); 322 node = mem_get_node(child);
332 assert(node);
333 child = node->next; // Next sibling. 323 child = node->next; // Next sibling.
334 } 324 }
335} 325}
@@ -381,7 +371,6 @@ void gfx_update_animation(Anima* anima, R t) {
381 // once (and potentially other non-joint intermediate nodes). 371 // once (and potentially other non-joint intermediate nodes).
382 node_idx root_index = anima->parent; 372 node_idx root_index = anima->parent;
383 SceneNode* root = mem_get_node(root_index); 373 SceneNode* root = mem_get_node(root_index);
384 assert(root);
385 // LOGD("Root: %u, child: %u", root_index.val, root->child.val); 374 // LOGD("Root: %u, child: %u", root_index.val, root->child.val);
386 const mat4 root_global_transform = gfx_get_node_global_transform(root); 375 const mat4 root_global_transform = gfx_get_node_global_transform(root);
387 const mat4 root_inv_global_transform = mat4_inverse(root_global_transform); 376 const mat4 root_inv_global_transform = mat4_inverse(root_global_transform);
@@ -391,8 +380,7 @@ void gfx_update_animation(Anima* anima, R t) {
391 compute_joint_matrices_rec( 380 compute_joint_matrices_rec(
392 child, root_global_transform, &root_inv_global_transform); 381 child, root_global_transform, &root_inv_global_transform);
393 SceneNode* node = mem_get_node(child); 382 SceneNode* node = mem_get_node(child);
394 assert(node); 383 child = node->next; // Next sibling.
395 child = node->next; // Next sibling.
396 } 384 }
397} 385}
398 386
diff --git a/gfx/src/scene/camera.c b/gfx/src/scene/camera.c
index df161c2..be7d806 100644
--- a/gfx/src/scene/camera.c
+++ b/gfx/src/scene/camera.c
@@ -5,29 +5,24 @@
5 5
6#include <assert.h> 6#include <assert.h>
7 7
8static void scene_camera_make(SceneCamera* camera) {
9 assert(camera);
10 camera->camera =
11 camera_perspective(/*fovy=*/90.0 * TO_RAD, /*aspect=*/16.0 / 9.0,
12 /*near=*/0.1, /*far=*/1000);
13}
14
15SceneCamera* gfx_make_camera() { 8SceneCamera* gfx_make_camera() {
16 SceneCamera* camera = mem_alloc_camera(); 9 SceneCamera* camera = mem_alloc_camera();
17 if (!camera) { 10
18 return 0; 11 camera->camera = camera_perspective(
19 } 12 /*fovy=*/90.0 * TO_RAD, /*aspect=*/16.0 / 9.0,
20 scene_camera_make(camera); 13 /*near=*/0.1, /*far=*/1000);
14
21 return camera; 15 return camera;
22} 16}
23 17
24void gfx_destroy_camera(SceneCamera** camera) { 18void gfx_destroy_camera(SceneCamera** camera) {
25 assert(camera); 19 assert(camera);
26 assert(*camera); 20 if (*camera) {
27 if ((*camera)->parent.val) { 21 if ((*camera)->parent.val) {
28 gfx_del_node((*camera)->parent); 22 gfx_del_node((*camera)->parent);
23 }
24 mem_free_camera(camera);
29 } 25 }
30 mem_free_camera(camera);
31} 26}
32 27
33void gfx_set_camera_camera(SceneCamera* scene_camera, Camera* camera) { 28void gfx_set_camera_camera(SceneCamera* scene_camera, Camera* camera) {
diff --git a/gfx/src/scene/light.c b/gfx/src/scene/light.c
index 31dca77..1046c82 100644
--- a/gfx/src/scene/light.c
+++ b/gfx/src/scene/light.c
@@ -9,7 +9,6 @@ static void make_environment_light(
9 Light* light, const EnvironmentLightDesc* desc) { 9 Light* light, const EnvironmentLightDesc* desc) {
10 assert(light); 10 assert(light);
11 assert(desc); 11 assert(desc);
12
13 light->type = EnvironmentLightType; 12 light->type = EnvironmentLightType;
14 light->environment.environment_map = desc->environment_map; 13 light->environment.environment_map = desc->environment_map;
15} 14}
@@ -18,9 +17,6 @@ Light* gfx_make_light(const LightDesc* desc) {
18 assert(desc); 17 assert(desc);
19 18
20 Light* light = mem_alloc_light(); 19 Light* light = mem_alloc_light();
21 if (!light) {
22 return 0;
23 }
24 20
25 switch (desc->type) { 21 switch (desc->type) {
26 case EnvironmentLightType: 22 case EnvironmentLightType:
@@ -37,9 +33,10 @@ Light* gfx_make_light(const LightDesc* desc) {
37 33
38void gfx_destroy_light(Light** light) { 34void gfx_destroy_light(Light** light) {
39 assert(light); 35 assert(light);
40 assert(*light); 36 if (*light) {
41 if ((*light)->parent.val) { 37 if ((*light)->parent.val) {
42 gfx_del_node((*light)->parent); 38 gfx_del_node((*light)->parent);
39 }
40 mem_free_light(light);
43 } 41 }
44 mem_free_light(light);
45} 42}
diff --git a/gfx/src/scene/material.c b/gfx/src/scene/material.c
index 6d6decb..b32d791 100644
--- a/gfx/src/scene/material.c
+++ b/gfx/src/scene/material.c
@@ -17,9 +17,6 @@ static void material_make(Material* material, const MaterialDesc* desc) {
17Material* gfx_make_material(const MaterialDesc* desc) { 17Material* gfx_make_material(const MaterialDesc* desc) {
18 assert(desc); 18 assert(desc);
19 Material* material = mem_alloc_material(); 19 Material* material = mem_alloc_material();
20 if (!material) {
21 return 0;
22 }
23 material_make(material, desc); 20 material_make(material, desc);
24 return material; 21 return material;
25} 22}
diff --git a/gfx/src/scene/mesh.c b/gfx/src/scene/mesh.c
index 689105c..1a93bed 100644
--- a/gfx/src/scene/mesh.c
+++ b/gfx/src/scene/mesh.c
@@ -17,9 +17,6 @@ static void mesh_make(Mesh* mesh, const MeshDesc* desc) {
17 17
18Mesh* gfx_make_mesh(const MeshDesc* desc) { 18Mesh* gfx_make_mesh(const MeshDesc* desc) {
19 Mesh* mesh = mem_alloc_mesh(); 19 Mesh* mesh = mem_alloc_mesh();
20 if (!mesh) {
21 return 0;
22 }
23 mesh_make(mesh, desc); 20 mesh_make(mesh, desc);
24 return mesh; 21 return mesh;
25} 22}
diff --git a/gfx/src/scene/node.c b/gfx/src/scene/node.c
index 2670680..2f761a2 100644
--- a/gfx/src/scene/node.c
+++ b/gfx/src/scene/node.c
@@ -19,9 +19,6 @@ static void scene_node_make(SceneNode* node) {
19 19
20SceneNode* gfx_make_node() { 20SceneNode* gfx_make_node() {
21 SceneNode* node = mem_alloc_node(); 21 SceneNode* node = mem_alloc_node();
22 if (!node) {
23 return 0;
24 }
25 scene_node_make(node); 22 scene_node_make(node);
26 return node; 23 return node;
27} 24}
@@ -29,60 +26,45 @@ SceneNode* gfx_make_node() {
29SceneNode* gfx_make_anima_node(Anima* anima) { 26SceneNode* gfx_make_anima_node(Anima* anima) {
30 assert(anima); 27 assert(anima);
31 SceneNode* node = gfx_make_node(); 28 SceneNode* node = gfx_make_node();
32 if (!node) { 29 node->type = AnimaNode;
33 return 0; 30 node->anima = mem_get_anima_index(anima);
34 } 31 anima->parent = mem_get_node_index(node);
35 node->type = AnimaNode;
36 node->anima = mem_get_anima_index(anima);
37 anima->parent = mem_get_node_index(node);
38 return node; 32 return node;
39} 33}
40 34
41SceneNode* gfx_make_camera_node(SceneCamera* camera) { 35SceneNode* gfx_make_camera_node(SceneCamera* camera) {
42 assert(camera); 36 assert(camera);
43 SceneNode* node = gfx_make_node(); 37 SceneNode* node = gfx_make_node();
44 if (!node) { 38 node->type = CameraNode;
45 return 0; 39 node->camera = mem_get_camera_index(camera);
46 } 40 camera->parent = mem_get_node_index(node);
47 node->type = CameraNode;
48 node->camera = mem_get_camera_index(camera);
49 camera->parent = mem_get_node_index(node);
50 return node; 41 return node;
51} 42}
52 43
53SceneNode* gfx_make_joint_node(Joint* joint) { 44SceneNode* gfx_make_joint_node(Joint* joint) {
54 assert(joint); 45 assert(joint);
55 SceneNode* node = gfx_make_node(); 46 SceneNode* node = gfx_make_node();
56 if (!node) { 47 node->type = JointNode;
57 return 0; 48 node->joint = mem_get_joint_index(joint);
58 } 49 joint->parent = mem_get_node_index(node);
59 node->type = JointNode;
60 node->joint = mem_get_joint_index(joint);
61 joint->parent = mem_get_node_index(node);
62 return node; 50 return node;
63} 51}
64 52
65SceneNode* gfx_make_light_node(Light* light) { 53SceneNode* gfx_make_light_node(Light* light) {
66 assert(light); 54 assert(light);
67 SceneNode* node = gfx_make_node(); 55 SceneNode* node = gfx_make_node();
68 if (!node) { 56 node->type = LightNode;
69 return 0; 57 node->light = mem_get_light_index(light);
70 } 58 light->parent = mem_get_node_index(node);
71 node->type = LightNode;
72 node->light = mem_get_light_index(light);
73 light->parent = mem_get_node_index(node);
74 return node; 59 return node;
75} 60}
76 61
77SceneNode* gfx_make_object_node(SceneObject* object) { 62SceneNode* gfx_make_object_node(SceneObject* object) {
78 assert(object); 63 assert(object);
79 SceneNode* node = gfx_make_node(); 64 SceneNode* node = gfx_make_node();
80 if (!node) { 65 node->type = ObjectNode;
81 return 0; 66 node->object = mem_get_object_index(object);
82 } 67 object->parent = mem_get_node_index(node);
83 node->type = ObjectNode;
84 node->object = mem_get_object_index(object);
85 object->parent = mem_get_node_index(node);
86 return node; 68 return node;
87} 69}
88 70
@@ -131,7 +113,6 @@ static void free_node_resource(SceneNode* node) {
131void gfx_construct_anima_node(SceneNode* node, Anima* anima) { 113void gfx_construct_anima_node(SceneNode* node, Anima* anima) {
132 assert(node); 114 assert(node);
133 assert(anima); 115 assert(anima);
134
135 free_node_resource(node); 116 free_node_resource(node);
136 node->type = AnimaNode; 117 node->type = AnimaNode;
137 node->anima = mem_get_anima_index(anima); 118 node->anima = mem_get_anima_index(anima);
@@ -141,7 +122,6 @@ void gfx_construct_anima_node(SceneNode* node, Anima* anima) {
141void gfx_construct_camera_node(SceneNode* node, SceneCamera* camera) { 122void gfx_construct_camera_node(SceneNode* node, SceneCamera* camera) {
142 assert(node); 123 assert(node);
143 assert(camera); 124 assert(camera);
144
145 free_node_resource(node); 125 free_node_resource(node);
146 node->type = CameraNode; 126 node->type = CameraNode;
147 node->camera = mem_get_camera_index(camera); 127 node->camera = mem_get_camera_index(camera);
@@ -153,7 +133,6 @@ void gfx_construct_camera_node(SceneNode* node, SceneCamera* camera) {
153void gfx_construct_joint_node(SceneNode* node, Joint* joint) { 133void gfx_construct_joint_node(SceneNode* node, Joint* joint) {
154 assert(node); 134 assert(node);
155 assert(joint); 135 assert(joint);
156
157 free_node_resource(node); 136 free_node_resource(node);
158 node->type = JointNode; 137 node->type = JointNode;
159 node->joint = mem_get_joint_index(joint); 138 node->joint = mem_get_joint_index(joint);
@@ -163,7 +142,6 @@ void gfx_construct_joint_node(SceneNode* node, Joint* joint) {
163void gfx_construct_light_node(SceneNode* node, Light* light) { 142void gfx_construct_light_node(SceneNode* node, Light* light) {
164 assert(node); 143 assert(node);
165 assert(light); 144 assert(light);
166
167 free_node_resource(node); 145 free_node_resource(node);
168 node->type = LightNode; 146 node->type = LightNode;
169 node->light = mem_get_light_index(light); 147 node->light = mem_get_light_index(light);
@@ -173,7 +151,6 @@ void gfx_construct_light_node(SceneNode* node, Light* light) {
173void gfx_construct_object_node(SceneNode* node, SceneObject* object) { 151void gfx_construct_object_node(SceneNode* node, SceneObject* object) {
174 assert(node); 152 assert(node);
175 assert(object); 153 assert(object);
176
177 free_node_resource(node); 154 free_node_resource(node);
178 node->type = ObjectNode; 155 node->type = ObjectNode;
179 node->object = mem_get_object_index(object); 156 node->object = mem_get_object_index(object);
@@ -199,20 +176,18 @@ static void destroy_node_rec(SceneNode* node) {
199 176
200void gfx_destroy_node(SceneNode** node) { 177void gfx_destroy_node(SceneNode** node) {
201 assert(node); 178 assert(node);
202 assert(*node); 179 if (*node) {
203 180 // Since the node and the whole hierarchy under it gets destroyed, there is
204 // Since the node and the whole hierarchy under it gets destroyed, there is 181 // no need to individually detach every node from its hierarchy. We can
205 // no need to individually detach every node from its hierarchy. We can simply 182 // simply detach the given node and then destroy it and its sub-hierarchy.
206 // detach the given node and then destroy it and its sub-hierarchy. 183 TREE_REMOVE(*node);
207 TREE_REMOVE(*node); 184 destroy_node_rec(*node);
208 185 *node = 0;
209 destroy_node_rec(*node); 186 }
210
211 *node = 0;
212} 187}
213 188
214// TODO: Think more about ownership of nodes and resources. Should this function 189// TODO: Think more about ownership of nodes and resources. Should this function
215// even exist? 190// even exist?
216void gfx_del_node(node_idx index) { 191void gfx_del_node(node_idx index) {
217 assert(index.val); 192 assert(index.val);
218 SceneNode* node = mem_get_node(index); 193 SceneNode* node = mem_get_node(index);
diff --git a/gfx/src/scene/object.c b/gfx/src/scene/object.c
index 64bb5a6..68a1340 100644
--- a/gfx/src/scene/object.c
+++ b/gfx/src/scene/object.c
@@ -15,20 +15,18 @@ static void scene_object_make(SceneObject* object) {
15 15
16SceneObject* gfx_make_object() { 16SceneObject* gfx_make_object() {
17 SceneObject* object = mem_alloc_object(); 17 SceneObject* object = mem_alloc_object();
18 if (!object) {
19 return 0;
20 }
21 scene_object_make(object); 18 scene_object_make(object);
22 return object; 19 return object;
23} 20}
24 21
25void gfx_destroy_object(SceneObject** object) { 22void gfx_destroy_object(SceneObject** object) {
26 assert(object); 23 assert(object);
27 assert(*object); 24 if (*object) {
28 if ((*object)->parent.val) { 25 if ((*object)->parent.val) {
29 gfx_del_node((*object)->parent); 26 gfx_del_node((*object)->parent);
27 }
28 mem_free_object(object);
30 } 29 }
31 mem_free_object(object);
32} 30}
33 31
34void gfx_set_object_transform(SceneObject* object, const mat4* transform) { 32void gfx_set_object_transform(SceneObject* object, const mat4* transform) {
@@ -80,8 +78,8 @@ void gfx_set_object_skeleton(SceneObject* object, const Skeleton* skeleton) {
80} 78}
81 79
82// TODO: Could compute just once if we changed the Object API to require an 80// TODO: Could compute just once if we changed the Object API to require an
83// object descriptor up front instead of allowing the client to add meshes 81// object descriptor up front instead of allowing the client to add meshes
84// and skeletons dynamically. 82// and skeletons dynamically.
85aabb3 gfx_calc_object_aabb(const SceneObject* object) { 83aabb3 gfx_calc_object_aabb(const SceneObject* object) {
86 assert(object); 84 assert(object);
87 85
diff --git a/gfx/src/scene/scene.c b/gfx/src/scene/scene.c
index c3dae9c..a6801ba 100644
--- a/gfx/src/scene/scene.c
+++ b/gfx/src/scene/scene.c
@@ -7,19 +7,16 @@
7 7
8Scene* gfx_make_scene(void) { 8Scene* gfx_make_scene(void) {
9 Scene* scene = mem_alloc_scene(); 9 Scene* scene = mem_alloc_scene();
10 if (!scene) { 10 scene->root = gfx_make_node();
11 return 0;
12 }
13 scene->root = gfx_make_node();
14 assert(scene->root);
15 return scene; 11 return scene;
16} 12}
17 13
18void gfx_destroy_scene(Scene** scene) { 14void gfx_destroy_scene(Scene** scene) {
19 assert(scene); 15 assert(scene);
20 assert(*scene); 16 if (*scene) {
21 gfx_destroy_node(&(*scene)->root); 17 gfx_destroy_node(&(*scene)->root);
22 mem_free_scene(scene); 18 mem_free_scene(scene);
19 }
23} 20}
24 21
25SceneNode* gfx_get_scene_root(Scene* scene) { 22SceneNode* gfx_get_scene_root(Scene* scene) {