summaryrefslogtreecommitdiff
path: root/gfx/src/scene
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/src/scene')
-rw-r--r--gfx/src/scene/camera.c42
-rw-r--r--gfx/src/scene/camera_impl.h12
-rw-r--r--gfx/src/scene/light.c45
-rw-r--r--gfx/src/scene/light_impl.h25
-rw-r--r--gfx/src/scene/material.c57
-rw-r--r--gfx/src/scene/material_impl.h17
-rw-r--r--gfx/src/scene/mesh.c25
-rw-r--r--gfx/src/scene/mesh_impl.h11
-rw-r--r--gfx/src/scene/node.c115
-rw-r--r--gfx/src/scene/node_impl.h38
-rw-r--r--gfx/src/scene/object.c71
-rw-r--r--gfx/src/scene/object_impl.h25
-rw-r--r--gfx/src/scene/scene.c43
-rw-r--r--gfx/src/scene/scene_graph.h67
-rw-r--r--gfx/src/scene/scene_impl.h17
-rw-r--r--gfx/src/scene/scene_memory.c148
-rw-r--r--gfx/src/scene/scene_memory.h130
-rw-r--r--gfx/src/scene/types.h21
18 files changed, 909 insertions, 0 deletions
diff --git a/gfx/src/scene/camera.c b/gfx/src/scene/camera.c
new file mode 100644
index 0000000..df161c2
--- /dev/null
+++ b/gfx/src/scene/camera.c
@@ -0,0 +1,42 @@
1#include "camera_impl.h"
2
3#include "node_impl.h"
4#include "scene_memory.h"
5
6#include <assert.h>
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() {
16 SceneCamera* camera = mem_alloc_camera();
17 if (!camera) {
18 return 0;
19 }
20 scene_camera_make(camera);
21 return camera;
22}
23
24void gfx_destroy_camera(SceneCamera** camera) {
25 assert(camera);
26 assert(*camera);
27 if ((*camera)->parent.val) {
28 gfx_del_node((*camera)->parent);
29 }
30 mem_free_camera(camera);
31}
32
33void gfx_set_camera_camera(SceneCamera* scene_camera, Camera* camera) {
34 assert(scene_camera);
35 assert(camera);
36 scene_camera->camera = *camera;
37}
38
39Camera* gfx_get_camera_camera(SceneCamera* camera) {
40 assert(camera);
41 return &camera->camera;
42}
diff --git a/gfx/src/scene/camera_impl.h b/gfx/src/scene/camera_impl.h
new file mode 100644
index 0000000..20c3890
--- /dev/null
+++ b/gfx/src/scene/camera_impl.h
@@ -0,0 +1,12 @@
1#pragma once
2
3#include <gfx/scene/camera.h>
4
5#include "types.h"
6
7#include <math/camera.h>
8
9typedef struct SceneCamera {
10 Camera camera;
11 node_idx parent; // Parent SceneNode.
12} SceneCamera;
diff --git a/gfx/src/scene/light.c b/gfx/src/scene/light.c
new file mode 100644
index 0000000..2ca1a01
--- /dev/null
+++ b/gfx/src/scene/light.c
@@ -0,0 +1,45 @@
1#include "light_impl.h"
2
3#include "node_impl.h"
4#include "scene_memory.h"
5
6#include <gfx/error.h>
7
8static void make_environment_light(Light* light,
9 const EnvironmentLightDesc* desc) {
10 assert(light);
11 assert(desc);
12
13 light->type = EnvironmentLightType;
14 light->environment.environment_map = desc->environment_map;
15}
16
17Light* gfx_make_light(const LightDesc* desc) {
18 assert(desc);
19
20 Light* light = mem_alloc_light();
21 if (!light) {
22 return 0;
23 }
24
25 switch (desc->type) {
26 case EnvironmentLightType:
27 make_environment_light(light, &desc->light.environment);
28 break;
29 default:
30 gfx_set_error("Unhandled light type");
31 gfx_destroy_light(&light);
32 return 0;
33 }
34
35 return light;
36}
37
38void gfx_destroy_light(Light** light) {
39 assert(light);
40 assert(*light);
41 if ((*light)->parent.val) {
42 gfx_del_node((*light)->parent);
43 }
44 mem_free_light(light);
45}
diff --git a/gfx/src/scene/light_impl.h b/gfx/src/scene/light_impl.h
new file mode 100644
index 0000000..1aa0bb4
--- /dev/null
+++ b/gfx/src/scene/light_impl.h
@@ -0,0 +1,25 @@
1#pragma once
2
3#include <gfx/scene/light.h>
4
5#include "types.h"
6
7typedef struct Texture Texture;
8
9/// An environment light.
10typedef struct EnvironmentLight {
11 const Texture* environment_map;
12 const Texture* irradiance_map; // Renderer implementation.
13 const Texture* prefiltered_environment_map; // Renderer implementation.
14 int max_reflection_lod; // Mandatory when prefiltered_environment_map is
15 // given.
16} EnvironmentLight;
17
18/// A scene light.
19typedef struct Light {
20 LightType type;
21 union {
22 EnvironmentLight environment;
23 };
24 node_idx parent; // Parent SceneNode.
25} Light;
diff --git a/gfx/src/scene/material.c b/gfx/src/scene/material.c
new file mode 100644
index 0000000..d44746a
--- /dev/null
+++ b/gfx/src/scene/material.c
@@ -0,0 +1,57 @@
1#include "material_impl.h"
2
3#include "scene_memory.h"
4
5#include <gfx/render_backend.h>
6
7static void material_make(Material* material, const MaterialDesc* desc) {
8 assert(material);
9 assert(desc);
10 assert(desc->num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
11 material->shader = desc->shader;
12 material->num_uniforms = desc->num_uniforms;
13 for (int i = 0; i < desc->num_uniforms; ++i) {
14 material->uniforms[i] = desc->uniforms[i];
15 }
16}
17
18Material* gfx_make_material(const MaterialDesc* desc) {
19 assert(desc);
20 Material* material = mem_alloc_material();
21 if (!material) {
22 return 0;
23 }
24 material_make(material, desc);
25 return material;
26}
27
28void gfx_destroy_material(Material** material) { mem_free_material(material); }
29
30static void set_uniform(ShaderProgram* prog, const ShaderUniform* uniform) {
31 switch (uniform->type) {
32 case UniformTexture:
33 gfx_set_texture_uniform(prog, uniform->name.str, uniform->value.texture);
34 break;
35 case UniformMat4:
36 gfx_set_mat4_uniform(prog, uniform->name.str, &uniform->value.mat4);
37 break;
38 case UniformVec3:
39 gfx_set_vec3_uniform(prog, uniform->name.str, uniform->value.vec3);
40 break;
41 case UniformVec4:
42 gfx_set_vec4_uniform(prog, uniform->name.str, uniform->value.vec4);
43 break;
44 case UniformFloat:
45 gfx_set_float_uniform(prog, uniform->name.str, uniform->value.scalar);
46 break;
47 }
48}
49
50void material_activate(const Material* material) {
51 assert(material);
52 gfx_activate_shader_program(material->shader);
53 for (int i = 0; i < material->num_uniforms; ++i) {
54 const ShaderUniform* uniform = &material->uniforms[i];
55 set_uniform(material->shader, uniform);
56 }
57}
diff --git a/gfx/src/scene/material_impl.h b/gfx/src/scene/material_impl.h
new file mode 100644
index 0000000..c680ccf
--- /dev/null
+++ b/gfx/src/scene/material_impl.h
@@ -0,0 +1,17 @@
1#pragma once
2
3#include <gfx/scene/material.h>
4
5typedef struct ShaderProgram ShaderProgram;
6
7typedef struct Material {
8 ShaderProgram* shader;
9 ShaderUniform uniforms[GFX_MAX_UNIFORMS_PER_MATERIAL];
10 int num_uniforms;
11} Material;
12
13/// Activate the material.
14///
15/// This activates the material's shader and configures the shader uniforms that
16/// are specific to the material.
17void material_activate(const Material* material);
diff --git a/gfx/src/scene/mesh.c b/gfx/src/scene/mesh.c
new file mode 100644
index 0000000..722eae7
--- /dev/null
+++ b/gfx/src/scene/mesh.c
@@ -0,0 +1,25 @@
1#include "mesh_impl.h"
2
3#include "scene_memory.h"
4
5#include <assert.h>
6
7static void mesh_make(Mesh* mesh, const MeshDesc* desc) {
8 assert(mesh);
9 assert(desc);
10 assert(desc->geometry);
11 assert(desc->material);
12 mesh->geometry = desc->geometry;
13 mesh->material = desc->material;
14}
15
16Mesh* gfx_make_mesh(const MeshDesc* desc) {
17 Mesh* mesh = mem_alloc_mesh();
18 if (!mesh) {
19 return 0;
20 }
21 mesh_make(mesh, desc);
22 return mesh;
23}
24
25void gfx_destroy_mesh(Mesh** mesh) { mem_free_mesh(mesh); }
diff --git a/gfx/src/scene/mesh_impl.h b/gfx/src/scene/mesh_impl.h
new file mode 100644
index 0000000..858b147
--- /dev/null
+++ b/gfx/src/scene/mesh_impl.h
@@ -0,0 +1,11 @@
1#pragma once
2
3#include <gfx/scene/mesh.h>
4
5typedef struct Mesh {
6 const Geometry* geometry;
7 const Material* material;
8} Mesh;
9
10// TODO: a mesh_render() that takes a transform, applies the material and the
11// transform, and then renders the geometry.
diff --git a/gfx/src/scene/node.c b/gfx/src/scene/node.c
new file mode 100644
index 0000000..7d7f69f
--- /dev/null
+++ b/gfx/src/scene/node.c
@@ -0,0 +1,115 @@
1#include "node_impl.h"
2
3#include "camera_impl.h"
4#include "light_impl.h"
5#include "object_impl.h"
6#include "scene_graph.h"
7#include "scene_memory.h"
8
9#include <assert.h>
10
11static void scene_node_make(SceneNode* node) {
12 assert(node);
13 node->type = LogicalNode;
14 node->transform = mat4_id();
15}
16
17SceneNode* gfx_make_node() {
18 SceneNode* node = mem_alloc_node();
19 if (!node) {
20 return 0;
21 }
22 scene_node_make(node);
23 return node;
24}
25
26SceneNode* gfx_make_camera_node(SceneCamera* camera) {
27 assert(camera);
28 SceneNode* node = gfx_make_node();
29 if (!node) {
30 return 0;
31 }
32 node->type = CameraNode;
33 node->camera = mem_get_camera_index(camera);
34 camera->parent = mem_get_node_index(node);
35 return node;
36}
37
38SceneNode* gfx_make_light_node(Light* light) {
39 assert(light);
40 SceneNode* node = gfx_make_node();
41 if (!node) {
42 return 0;
43 }
44 node->type = LightNode;
45 node->light = mem_get_light_index(light);
46 light->parent = mem_get_node_index(node);
47 return node;
48}
49
50SceneNode* gfx_make_object_node(SceneObject* object) {
51 assert(object);
52 SceneNode* node = gfx_make_node();
53 if (!node) {
54 return 0;
55 }
56 node->type = ObjectNode;
57 node->object = mem_get_object_index(object);
58 object->parent = mem_get_node_index(node);
59 return node;
60}
61
62void gfx_destroy_node(SceneNode** node) {
63 assert(node);
64 assert(*node);
65
66 // Destroy the node's resources.
67 // Camera.
68 if ((*node)->type == CameraNode) {
69 SceneCamera* camera = mem_get_camera((*node)->camera);
70 camera->parent.val = 0; // Avoid recursive call into gfx_destroy_node().
71 gfx_destroy_camera(&camera);
72 }
73 // TODO: free light.
74 // Object.
75 if ((*node)->type == ObjectNode) {
76 SceneObject* object = mem_get_object((*node)->object);
77 object->parent.val = 0; // Avoid recursive call into gfx_destroy_node().
78 gfx_destroy_object(&object);
79 }
80
81 TREE_REMOVE(*node);
82 mem_free_node(node);
83}
84
85void gfx_del_node(node_idx index) {
86 assert(index.val);
87 SceneNode* node = mem_get_node(index);
88 assert(node);
89 TREE_REMOVE(node);
90 mem_free_node(&node);
91}
92
93void gfx_set_node_parent(SceneNode* child, SceneNode* parent) {
94 assert(child);
95 assert(parent);
96 SET_PARENT(child, parent);
97}
98
99void gfx_set_node_transform(SceneNode* node, const mat4* transform) {
100 assert(node);
101 assert(transform);
102 node->transform = *transform;
103}
104
105void gfx_set_node_position(SceneNode* node, const vec3* position) {
106 assert(node);
107 assert(position);
108 mat4_set_v3(&node->transform, *position);
109}
110
111void gfx_set_node_rotation(SceneNode* node, const mat4* rotation) {
112 assert(node);
113 assert(rotation);
114 mat4_set_3x3(&node->transform, *rotation);
115}
diff --git a/gfx/src/scene/node_impl.h b/gfx/src/scene/node_impl.h
new file mode 100644
index 0000000..ce3b769
--- /dev/null
+++ b/gfx/src/scene/node_impl.h
@@ -0,0 +1,38 @@
1#pragma once
2
3#include <gfx/scene/node.h>
4
5#include "types.h"
6
7#include <math/mat4.h>
8
9/// Scene node type.
10typedef enum NodeType {
11 CameraNode,
12 LightNode,
13 LogicalNode,
14 ObjectNode
15} NodeType;
16
17/// Scene node.
18///
19/// The SceneNode owns its cameras, objects, lights and child nodes. These
20/// together form a strict tree hierarchy and not a more general DAG.
21typedef struct SceneNode {
22 NodeType type;
23 union {
24 camera_idx camera;
25 light_idx light;
26 object_idx object;
27 };
28 mat4 transform; // Transformation for this node and its children.
29 node_idx parent; // Parent SceneNode.
30 node_idx child; // First child SceneNode.
31 node_idx next; // Next sibling SceneNode.
32 node_idx prev; // Previous sibling SceneNode.
33} SceneNode;
34
35/// Destroy a node given its index.
36///
37/// The node is conveniently removed from the scene graph.
38void gfx_del_node(node_idx);
diff --git a/gfx/src/scene/object.c b/gfx/src/scene/object.c
new file mode 100644
index 0000000..7f23e92
--- /dev/null
+++ b/gfx/src/scene/object.c
@@ -0,0 +1,71 @@
1#include "object_impl.h"
2
3#include "node_impl.h"
4#include "scene_memory.h"
5
6#include <assert.h>
7
8static void scene_object_make(SceneObject* object) {
9 assert(object);
10 object->transform = mat4_id();
11}
12
13SceneObject* gfx_make_object() {
14 SceneObject* object = mem_alloc_object();
15 if (!object) {
16 return 0;
17 }
18 scene_object_make(object);
19 return object;
20}
21
22void gfx_destroy_object(SceneObject** object) {
23 assert(object);
24 assert(*object);
25 if ((*object)->parent.val) {
26 gfx_del_node((*object)->parent);
27 }
28 mem_free_object(object);
29}
30
31void gfx_set_object_transform(SceneObject* object, const mat4* transform) {
32 assert(object);
33 assert(transform);
34 object->transform = *transform;
35}
36
37void gfx_add_object_mesh(SceneObject* object, Mesh* mesh) {
38 assert(object);
39 assert(mesh);
40
41 MeshLink* link = mem_alloc_mesh_link();
42 assert(link);
43 link->mesh = mem_get_mesh_index(mesh);
44 link->next = object->mesh_link;
45 object->mesh_link = mem_get_mesh_link_index(link);
46}
47
48void gfx_remove_object_mesh(SceneObject* object, Mesh* mesh) {
49 assert(object);
50 assert(mesh);
51
52 MeshLink* prev = 0;
53 const mesh_idx mesh_index = mem_get_mesh_index(mesh);
54
55 // Find the MeshLink in the object that contains the given mesh.
56 for (mesh_link_idx mesh_link_index = object->mesh_link;
57 mesh_link_index.val;) {
58 MeshLink* mesh_link = mem_get_mesh_link(mesh_link_index);
59 if (mesh_link->mesh.val == mesh_index.val) {
60 if (prev) {
61 prev->next = mesh_link->next;
62 } else {
63 object->mesh_link = mesh_link->next;
64 }
65 mem_free_mesh_link(&mesh_link);
66 break;
67 }
68 prev = mesh_link;
69 mesh_link_index = mesh_link->next;
70 }
71}
diff --git a/gfx/src/scene/object_impl.h b/gfx/src/scene/object_impl.h
new file mode 100644
index 0000000..bd3fdbc
--- /dev/null
+++ b/gfx/src/scene/object_impl.h
@@ -0,0 +1,25 @@
1#pragma once
2
3#include <gfx/scene/object.h>
4
5#include "types.h"
6
7#include <math/mat4.h>
8
9typedef struct MeshLink {
10 mesh_idx mesh;
11 mesh_link_idx next; // Next MeshLink in the list.
12} MeshLink;
13
14/// Scene object.
15///
16/// A SceneObject does not own its Meshes, and they are instead shared for
17/// re-use. The SceneObject consequently embeds a list of MeshLinks as opposed
18/// to a list of Meshes. The MeshLinks define a list of Meshes, which can be
19/// different for each SceneObject. Each SceneObject may then have a unique list
20/// of Meshes, and the Meshes are re-used.
21typedef struct SceneObject {
22 mat4 transform;
23 mesh_link_idx mesh_link; // First MeshLink in the list.
24 node_idx parent; // Parent SceneNode.
25} SceneObject;
diff --git a/gfx/src/scene/scene.c b/gfx/src/scene/scene.c
new file mode 100644
index 0000000..9e974de
--- /dev/null
+++ b/gfx/src/scene/scene.c
@@ -0,0 +1,43 @@
1#include "scene_impl.h"
2
3#include "camera_impl.h"
4#include "node_impl.h"
5#include "object_impl.h"
6#include "scene_graph.h"
7#include "scene_memory.h"
8
9static void scene_destroy_rec(node_idx node_index) {
10 assert(node_index.val);
11
12 SceneNode* node = mem_get_node(node_index);
13 assert(node);
14
15 // First child.
16 if (node->child.val) {
17 scene_destroy_rec(node->child);
18 }
19
20 // Right sibling.
21 if (node->next.val) {
22 scene_destroy_rec(node->next);
23 }
24
25 gfx_destroy_node(&node);
26}
27
28void scene_make(Scene* scene) {
29 assert(scene);
30 SceneNode* root = gfx_make_node();
31 assert(root);
32 scene->root = mem_get_node_index(root);
33}
34
35void scene_destroy(Scene* scene) {
36 assert(scene);
37 scene_destroy_rec(scene->root);
38}
39
40SceneNode* gfx_get_scene_root(Scene* scene) {
41 assert(scene);
42 return mem_get_node(scene->root);
43}
diff --git a/gfx/src/scene/scene_graph.h b/gfx/src/scene/scene_graph.h
new file mode 100644
index 0000000..b9b3a14
--- /dev/null
+++ b/gfx/src/scene/scene_graph.h
@@ -0,0 +1,67 @@
1/// Functions for list manipulation.
2#pragma once
3
4#include "scene_memory.h"
5
6// Note that SceneMemory guarantees that index 0 can be regarded as an invalid
7// index.
8
9#define MEM_GET(INDEX) \
10 _Generic((INDEX), camera_idx \
11 : mem_get_camera, material_idx \
12 : mem_get_material, mesh_idx \
13 : mem_get_mesh, mesh_link_idx \
14 : mem_get_mesh_link, node_idx \
15 : mem_get_node, object_idx \
16 : mem_get_object, scene_idx \
17 : mem_get_scene)(INDEX)
18
19#define MEM_GET_INDEX(ITEM) \
20 _Generic((ITEM), SceneCamera * \
21 : mem_get_camera_index, Material * \
22 : mem_get_material_index, Mesh * \
23 : mem_get_mesh_index, MeshLink * \
24 : mem_get_mesh_link_index, SceneNode * \
25 : mem_get_node_index, SceneObject * \
26 : mem_get_object_index, Scene * \
27 : mem_get_scene_index)(ITEM)
28
29#define LIST_PREPEND(HEAD_INDEX, ITEM) \
30 ITEM->next = HEAD_INDEX; \
31 if (HEAD_INDEX.val) { \
32 typeof(ITEM) old_head = MEM_GET(HEAD_INDEX); \
33 old_head->prev = MEM_GET_INDEX(ITEM); \
34 } \
35 HEAD_INDEX = MEM_GET_INDEX(ITEM);
36
37#define LIST_REMOVE(ITEM) \
38 if ((ITEM)->prev.val) { \
39 typeof(ITEM) prev_sibling = MEM_GET((ITEM)->prev); \
40 prev_sibling->next = (ITEM)->next; \
41 } \
42 if ((ITEM)->next.val) { \
43 typeof(ITEM) next_sibling = MEM_GET((ITEM)->next); \
44 next_sibling->prev = (ITEM)->prev; \
45 }
46
47#define SET_PARENT(CHILD, PARENT) \
48 assert(CHILD); \
49 if (CHILD->parent.val) { \
50 LIST_REMOVE(CHILD); \
51 } \
52 if (parent) { \
53 LIST_PREPEND(PARENT->CHILD, CHILD); \
54 }
55
56#define TREE_REMOVE(ITEM) \
57 if ((ITEM)->prev.val) { \
58 typeof(ITEM) prev_sibling = MEM_GET((ITEM)->prev); \
59 prev_sibling->next = (ITEM)->next; \
60 } \
61 if ((ITEM)->next.val) { \
62 typeof(ITEM) next_sibling = MEM_GET((ITEM)->next); \
63 next_sibling->prev = (ITEM)->prev; \
64 } \
65 if ((ITEM)->parent.val) { \
66 MEM_GET((ITEM)->parent)->child.val = 0; \
67 }
diff --git a/gfx/src/scene/scene_impl.h b/gfx/src/scene/scene_impl.h
new file mode 100644
index 0000000..e0c25bf
--- /dev/null
+++ b/gfx/src/scene/scene_impl.h
@@ -0,0 +1,17 @@
1#pragma once
2
3#include <gfx/scene/scene.h>
4
5#include "types.h"
6
7typedef struct Scene {
8 node_idx root;
9 scene_idx next;
10 scene_idx prev;
11} Scene;
12
13/// Create a new scene.
14void scene_make(Scene*);
15
16/// Destroy the scene.
17void scene_destroy(Scene*);
diff --git a/gfx/src/scene/scene_memory.c b/gfx/src/scene/scene_memory.c
new file mode 100644
index 0000000..cd4a79c
--- /dev/null
+++ b/gfx/src/scene/scene_memory.c
@@ -0,0 +1,148 @@
1#include "scene_memory.h"
2
3#include <gfx/sizes.h>
4
5#include "camera_impl.h"
6#include "light_impl.h"
7#include "material_impl.h"
8#include "mesh_impl.h"
9#include "node_impl.h"
10#include "object_impl.h"
11#include "scene_impl.h"
12#include "types.h"
13
14#include <mempool.h>
15
16DEF_MEMPOOL(camera_pool, SceneCamera, GFX_MAX_NUM_CAMERAS)
17DEF_MEMPOOL(light_pool, Light, GFX_MAX_NUM_LIGHTS)
18DEF_MEMPOOL(material_pool, Material, GFX_MAX_NUM_MATERIALS)
19DEF_MEMPOOL(mesh_pool, Mesh, GFX_MAX_NUM_MESHES)
20DEF_MEMPOOL(mesh_link_pool, MeshLink, GFX_MAX_NUM_MESH_LINKS)
21DEF_MEMPOOL(node_pool, SceneNode, GFX_MAX_NUM_NODES)
22DEF_MEMPOOL(object_pool, SceneObject, GFX_MAX_NUM_OBJECTS)
23DEF_MEMPOOL(scene_pool, Scene, GFX_MAX_NUM_SCENES)
24
25/// Scene memory.
26///
27/// Holds memory pools for every type of scene object.
28typedef struct SceneMemory {
29 camera_pool cameras;
30 light_pool lights;
31 material_pool materials;
32 mesh_pool meshes;
33 mesh_link_pool mesh_links;
34 node_pool nodes;
35 object_pool objects;
36 scene_pool scenes;
37} SceneMemory;
38
39static SceneMemory mem;
40
41#define ALLOC_DUMMY(POOL) \
42 assert(mempool_get_block_index(POOL, mempool_alloc(POOL)) == 0)
43
44void scene_mem_init() {
45 mempool_make(&mem.cameras);
46 mempool_make(&mem.lights);
47 mempool_make(&mem.materials);
48 mempool_make(&mem.meshes);
49 mempool_make(&mem.mesh_links);
50 mempool_make(&mem.nodes);
51 mempool_make(&mem.objects);
52 mempool_make(&mem.scenes);
53
54 // Allocate dummy objects at index 0 to guarantee that no objects allocated by
55 // the caller map to index 0.
56 ALLOC_DUMMY(&mem.cameras);
57 ALLOC_DUMMY(&mem.lights);
58 ALLOC_DUMMY(&mem.materials);
59 ALLOC_DUMMY(&mem.meshes);
60 ALLOC_DUMMY(&mem.mesh_links);
61 ALLOC_DUMMY(&mem.nodes);
62 ALLOC_DUMMY(&mem.objects);
63 ALLOC_DUMMY(&mem.scenes);
64}
65
66void scene_mem_destroy() {}
67
68// Memory allocation.
69SceneCamera* mem_alloc_camera() { return mempool_alloc(&mem.cameras); }
70Light* mem_alloc_light() { return mempool_alloc(&mem.lights); }
71Material* mem_alloc_material() { return mempool_alloc(&mem.materials); }
72Mesh* mem_alloc_mesh() { return mempool_alloc(&mem.meshes); }
73MeshLink* mem_alloc_mesh_link() { return mempool_alloc(&mem.mesh_links); }
74SceneNode* mem_alloc_node() { return mempool_alloc(&mem.nodes); }
75SceneObject* mem_alloc_object() { return mempool_alloc(&mem.objects); }
76Scene* mem_alloc_scene() { return mempool_alloc(&mem.scenes); }
77
78// Memory free.
79void mem_free_camera(SceneCamera** camera) {
80 mempool_free(&mem.cameras, camera);
81}
82void mem_free_light(Light** light) { mempool_free(&mem.lights, light); }
83void mem_free_material(Material** material) {
84 mempool_free(&mem.materials, material);
85}
86void mem_free_mesh(Mesh** mesh) { mempool_free(&mem.meshes, mesh); }
87void mem_free_mesh_link(MeshLink** mesh_link) {
88 mempool_free(&mem.mesh_links, mesh_link);
89}
90void mem_free_node(SceneNode** node) { mempool_free(&mem.nodes, node); }
91void mem_free_object(SceneObject** object) {
92 mempool_free(&mem.objects, object);
93}
94void mem_free_scene(Scene** scene) { mempool_free(&mem.scenes, scene); }
95
96// Query by index.
97SceneCamera* mem_get_camera(camera_idx index) {
98 return mempool_get_block(&mem.cameras, index.val);
99}
100Light* mem_get_light(light_idx index) {
101 return mempool_get_block(&mem.lights, index.val);
102}
103Material* mem_get_material(material_idx index) {
104 return mempool_get_block(&mem.materials, index.val);
105}
106Mesh* mem_get_mesh(mesh_idx index) {
107 return mempool_get_block(&mem.meshes, index.val);
108}
109MeshLink* mem_get_mesh_link(mesh_link_idx index) {
110 return mempool_get_block(&mem.mesh_links, index.val);
111}
112SceneNode* mem_get_node(node_idx index) {
113 return mempool_get_block(&mem.nodes, index.val);
114}
115SceneObject* mem_get_object(object_idx index) {
116 return mempool_get_block(&mem.objects, index.val);
117}
118Scene* mem_get_scene(scene_idx index) {
119 return mempool_get_block(&mem.scenes, index.val);
120}
121
122// Map object to index.
123camera_idx mem_get_camera_index(const SceneCamera* camera) {
124 return (camera_idx){.val = mempool_get_block_index(&mem.cameras, camera)};
125}
126light_idx mem_get_light_index(const Light* light) {
127 return (light_idx){.val = mempool_get_block_index(&mem.lights, light)};
128}
129material_idx mem_get_material_index(const Material* material) {
130 return (material_idx){.val =
131 mempool_get_block_index(&mem.materials, material)};
132}
133mesh_idx mem_get_mesh_index(const Mesh* mesh) {
134 return (mesh_idx){.val = mempool_get_block_index(&mem.meshes, mesh)};
135}
136mesh_link_idx mem_get_mesh_link_index(const MeshLink* mesh_link) {
137 return (mesh_link_idx){
138 .val = mempool_get_block_index(&mem.mesh_links, mesh_link)};
139}
140node_idx mem_get_node_index(const SceneNode* node) {
141 return (node_idx){.val = mempool_get_block_index(&mem.nodes, node)};
142}
143object_idx mem_get_object_index(const SceneObject* object) {
144 return (object_idx){.val = mempool_get_block_index(&mem.objects, object)};
145}
146scene_idx mem_get_scene_index(const Scene* scene) {
147 return (scene_idx){.val = mempool_get_block_index(&mem.scenes, scene)};
148}
diff --git a/gfx/src/scene/scene_memory.h b/gfx/src/scene/scene_memory.h
new file mode 100644
index 0000000..dff5bd8
--- /dev/null
+++ b/gfx/src/scene/scene_memory.h
@@ -0,0 +1,130 @@
1/// Memory management of scene objects.
2#pragma once
3
4#include "types.h"
5
6typedef struct Light Light;
7typedef struct Material Material;
8typedef struct Mesh Mesh;
9typedef struct MeshLink MeshLink;
10typedef struct SceneCamera SceneCamera;
11typedef struct SceneNode SceneNode;
12typedef struct SceneObject SceneObject;
13typedef struct Scene Scene;
14
15/// Initialize scene memory.
16///
17/// The scene memory guarantees that every object maps to an index different
18/// than 0. In this way, 0 can be used as a special index to denote "no value".
19void scene_mem_init();
20
21/// Destroy the scene memory.
22void scene_mem_destroy();
23
24/// ----------------------------------------------------------------------------
25/// Memory allocation.
26/// ----------------------------------------------------------------------------
27
28/// Allocate space for a camera.
29SceneCamera* mem_alloc_camera();
30
31/// Allocate space for a light.
32Light* mem_alloc_light();
33
34/// Allocate space for a material.
35Material* mem_alloc_material();
36
37/// Allocate space for a mesh.
38Mesh* mem_alloc_mesh();
39
40/// Allocate space for a mesh link.
41MeshLink* mem_alloc_mesh_link();
42
43/// Allocate space for a scene node.
44SceneNode* mem_alloc_node();
45
46/// Allocate space for a scene object.
47SceneObject* mem_alloc_object();
48
49/// Allocate space for a scene.
50Scene* mem_alloc_scene();
51
52/// Free the camera.
53void mem_free_camera(SceneCamera**);
54
55/// Free the light.
56void mem_free_light(Light**);
57
58/// Free the material.
59void mem_free_material(Material**);
60
61/// Free the mesh.
62void mem_free_mesh(Mesh**);
63
64/// Free the mesh link.
65void mem_free_mesh_link(MeshLink**);
66
67/// Free the scene node.
68void mem_free_node(SceneNode**);
69
70/// Free the scene object.
71void mem_free_object(SceneObject**);
72
73/// Free the scene.
74void mem_free_scene(Scene**);
75
76/// ----------------------------------------------------------------------------
77/// Query objects by index.
78/// ----------------------------------------------------------------------------
79
80/// Get a camera by index.
81SceneCamera* mem_get_camera(camera_idx);
82
83/// Get a light by index.
84Light* mem_get_light(light_idx);
85
86/// Get a material by index.
87Material* mem_get_material(material_idx);
88
89/// Get a mesh by index.
90Mesh* mem_get_mesh(mesh_idx);
91
92/// Get a mesh link by index.
93MeshLink* mem_get_mesh_link(mesh_link_idx);
94
95/// Get a node by index.
96SceneNode* mem_get_node(node_idx);
97
98/// Get an object by index.
99SceneObject* mem_get_object(object_idx);
100
101/// Get a scene by index.
102Scene* mem_get_scene(scene_idx);
103
104/// ----------------------------------------------------------------------------
105/// Map objects to indices.
106/// ----------------------------------------------------------------------------
107
108/// Get the camera's index.
109camera_idx mem_get_camera_index(const SceneCamera*);
110
111/// Get the light's index.
112light_idx mem_get_light_index(const Light*);
113
114/// Get the material's index.
115material_idx mem_get_material_index(const Material*);
116
117/// Get the mesh's index.
118mesh_idx mem_get_mesh_index(const Mesh*);
119
120/// Get the mesh link's index.
121mesh_link_idx mem_get_mesh_link_index(const MeshLink*);
122
123/// Get the node's index.
124node_idx mem_get_node_index(const SceneNode*);
125
126/// Get the object's index.
127object_idx mem_get_object_index(const SceneObject*);
128
129/// Get the scene's index.
130scene_idx mem_get_scene_index(const Scene*);
diff --git a/gfx/src/scene/types.h b/gfx/src/scene/types.h
new file mode 100644
index 0000000..2863ac7
--- /dev/null
+++ b/gfx/src/scene/types.h
@@ -0,0 +1,21 @@
1#pragma once
2
3#include <stdint.h>
4
5typedef uint16_t gfx_idx;
6
7// Strongly-typed indices.
8
9#define DEF_STRONG_INDEX(TYPE_NAME) \
10 typedef struct TYPE_NAME##_idx { \
11 gfx_idx val; \
12 } TYPE_NAME##_idx;
13
14DEF_STRONG_INDEX(camera)
15DEF_STRONG_INDEX(light)
16DEF_STRONG_INDEX(material)
17DEF_STRONG_INDEX(mesh)
18DEF_STRONG_INDEX(mesh_link)
19DEF_STRONG_INDEX(node)
20DEF_STRONG_INDEX(object)
21DEF_STRONG_INDEX(scene)