diff options
-rw-r--r-- | game/src/plugins/texture_view.c | 4 | ||||
-rw-r--r-- | game/src/plugins/viewer.c | 2 | ||||
-rw-r--r-- | gfx/include/gfx/scene/object.h | 22 | ||||
-rw-r--r-- | gfx/src/asset/model.c | 16 | ||||
-rw-r--r-- | gfx/src/renderer/renderer.c | 2 | ||||
-rw-r--r-- | gfx/src/scene/object.c | 105 | ||||
-rw-r--r-- | gfx/src/scene/object_impl.h | 6 | ||||
-rw-r--r-- | gfx/src/util/skyquad.c | 3 |
8 files changed, 66 insertions, 94 deletions
diff --git a/game/src/plugins/texture_view.c b/game/src/plugins/texture_view.c index b624f46..52dff57 100644 --- a/game/src/plugins/texture_view.c +++ b/game/src/plugins/texture_view.c | |||
@@ -73,11 +73,11 @@ bool init(Game* game, State** pp_state) { | |||
73 | goto cleanup; | 73 | goto cleanup; |
74 | } | 74 | } |
75 | 75 | ||
76 | SceneObject* object = gfx_make_object(); | 76 | SceneObject* object = |
77 | gfx_make_object(&(ObjectDesc){.num_meshes = 1, .meshes = {mesh}}); | ||
77 | if (!object) { | 78 | if (!object) { |
78 | goto cleanup; | 79 | goto cleanup; |
79 | } | 80 | } |
80 | gfx_add_object_mesh(object, mesh); | ||
81 | 81 | ||
82 | if (!(state->scene = gfx_make_scene())) { | 82 | if (!(state->scene = gfx_make_scene())) { |
83 | goto cleanup; | 83 | goto cleanup; |
diff --git a/game/src/plugins/viewer.c b/game/src/plugins/viewer.c index 88821af..4f4ef03 100644 --- a/game/src/plugins/viewer.c +++ b/game/src/plugins/viewer.c | |||
@@ -195,7 +195,7 @@ static void render_bounding_boxes_rec(ImmRenderer* imm, const SceneNode* node) { | |||
195 | // pose). | 195 | // pose). |
196 | const mat4 model = gfx_get_node_global_transform(node); | 196 | const mat4 model = gfx_get_node_global_transform(node); |
197 | const SceneObject* obj = gfx_get_node_object(node); | 197 | const SceneObject* obj = gfx_get_node_object(node); |
198 | const aabb3 box = gfx_calc_object_aabb(obj); | 198 | const aabb3 box = gfx_get_object_aabb(obj); |
199 | gfx_imm_set_model_matrix(imm, &model); | 199 | gfx_imm_set_model_matrix(imm, &model); |
200 | gfx_imm_draw_aabb3(imm, box); | 200 | gfx_imm_draw_aabb3(imm, box); |
201 | } | 201 | } |
diff --git a/gfx/include/gfx/scene/object.h b/gfx/include/gfx/scene/object.h index ccc9999..891c3cd 100644 --- a/gfx/include/gfx/scene/object.h +++ b/gfx/include/gfx/scene/object.h | |||
@@ -1,5 +1,7 @@ | |||
1 | #pragma once | 1 | #pragma once |
2 | 2 | ||
3 | #include <gfx/sizes.h> | ||
4 | |||
3 | #include <math/fwd.h> | 5 | #include <math/fwd.h> |
4 | 6 | ||
5 | #include <math/aabb3.h> | 7 | #include <math/aabb3.h> |
@@ -10,8 +12,13 @@ typedef struct Skeleton Skeleton; | |||
10 | 12 | ||
11 | typedef struct SceneObject SceneObject; | 13 | typedef struct SceneObject SceneObject; |
12 | 14 | ||
15 | typedef struct ObjectDesc { | ||
16 | size_t num_meshes; | ||
17 | Mesh* meshes[GFX_MAX_NUM_MESHES]; | ||
18 | } ObjectDesc; | ||
19 | |||
13 | /// Create a new object. | 20 | /// Create a new object. |
14 | SceneObject* gfx_make_object(); | 21 | SceneObject* gfx_make_object(const ObjectDesc*); |
15 | 22 | ||
16 | /// Destroy the object. | 23 | /// Destroy the object. |
17 | /// | 24 | /// |
@@ -19,19 +26,10 @@ SceneObject* gfx_make_object(); | |||
19 | /// node is destroyed. | 26 | /// node is destroyed. |
20 | void gfx_destroy_object(SceneObject**); | 27 | void gfx_destroy_object(SceneObject**); |
21 | 28 | ||
22 | /// Sets the object's transformation matrix. | ||
23 | void gfx_set_object_transform(SceneObject*, const mat4*); | ||
24 | |||
25 | /// Add a mesh to the object. | ||
26 | void gfx_add_object_mesh(SceneObject*, Mesh*); | ||
27 | |||
28 | /// Remove a mesh from the object. | ||
29 | void gfx_remove_object_mesh(SceneObject*, Mesh*); | ||
30 | |||
31 | /// Set the object's skeleton. | 29 | /// Set the object's skeleton. |
32 | void gfx_set_object_skeleton(SceneObject*, const Skeleton*); | 30 | void gfx_set_object_skeleton(SceneObject*, const Skeleton*); |
33 | 31 | ||
34 | /// Computes the object's bounding box. | 32 | /// Gets the object's bounding box. |
35 | /// | 33 | /// |
36 | /// The object's bounding box is the bounding box of its mesh geometries. | 34 | /// The object's bounding box is the bounding box of its mesh geometries. |
37 | aabb3 gfx_calc_object_aabb(const SceneObject*); | 35 | aabb3 gfx_get_object_aabb(const SceneObject*); |
diff --git a/gfx/src/asset/model.c b/gfx/src/asset/model.c index 05e6e91..37f129e 100644 --- a/gfx/src/asset/model.c +++ b/gfx/src/asset/model.c | |||
@@ -910,10 +910,7 @@ static bool load_meshes( | |||
910 | for (cgltf_size m = 0; m < data->meshes_count; ++m) { | 910 | for (cgltf_size m = 0; m < data->meshes_count; ++m) { |
911 | const cgltf_mesh* mesh = &data->meshes[m]; | 911 | const cgltf_mesh* mesh = &data->meshes[m]; |
912 | 912 | ||
913 | scene_objects[m] = gfx_make_object(); | 913 | ObjectDesc object_desc = {0}; |
914 | if (!scene_objects[m]) { | ||
915 | return false; | ||
916 | } | ||
917 | 914 | ||
918 | for (cgltf_size p = 0; p < mesh->primitives_count; ++p) { | 915 | for (cgltf_size p = 0; p < mesh->primitives_count; ++p) { |
919 | assert(next_mesh < primitive_count); | 916 | assert(next_mesh < primitive_count); |
@@ -1173,11 +1170,18 @@ static bool load_meshes( | |||
1173 | return false; | 1170 | return false; |
1174 | } | 1171 | } |
1175 | 1172 | ||
1176 | gfx_add_object_mesh(scene_objects[m], meshes[next_mesh]); | 1173 | assert(object_desc.num_meshes < GFX_MAX_NUM_MESHES); |
1174 | object_desc.meshes[object_desc.num_meshes] = meshes[next_mesh]; | ||
1175 | object_desc.num_meshes++; | ||
1177 | 1176 | ||
1178 | ++next_mesh; | 1177 | ++next_mesh; |
1179 | } // glTF mesh primitive / gfx Mesh. | 1178 | } // glTF mesh primitive / gfx Mesh. |
1180 | } // glTF mesh / gfx SceneObject. | 1179 | |
1180 | scene_objects[m] = gfx_make_object(&object_desc); | ||
1181 | if (!scene_objects[m]) { | ||
1182 | return false; | ||
1183 | } | ||
1184 | } // glTF mesh / gfx SceneObject. | ||
1181 | 1185 | ||
1182 | return true; | 1186 | return true; |
1183 | } | 1187 | } |
diff --git a/gfx/src/renderer/renderer.c b/gfx/src/renderer/renderer.c index dbfc62b..161eed2 100644 --- a/gfx/src/renderer/renderer.c +++ b/gfx/src/renderer/renderer.c | |||
@@ -241,7 +241,7 @@ static void draw_recursively( | |||
241 | 241 | ||
242 | // TODO: Avoid computing matrices like Modelview or MVP if the shader does | 242 | // TODO: Avoid computing matrices like Modelview or MVP if the shader does |
243 | // not use them. | 243 | // not use them. |
244 | const mat4 model_matrix = mat4_mul(node_transform, object->transform); | 244 | const mat4 model_matrix = node_transform; |
245 | const mat4 modelview = mat4_mul(*state->view_matrix, model_matrix); | 245 | const mat4 modelview = mat4_mul(*state->view_matrix, model_matrix); |
246 | const mat4 mvp = mat4_mul(*state->projection, modelview); | 246 | const mat4 mvp = mat4_mul(*state->projection, modelview); |
247 | 247 | ||
diff --git a/gfx/src/scene/object.c b/gfx/src/scene/object.c index 68a1340..9291feb 100644 --- a/gfx/src/scene/object.c +++ b/gfx/src/scene/object.c | |||
@@ -8,66 +8,61 @@ | |||
8 | 8 | ||
9 | #include <assert.h> | 9 | #include <assert.h> |
10 | 10 | ||
11 | static void scene_object_make(SceneObject* object) { | 11 | static aabb3 calc_object_aabb(const SceneObject* object) { |
12 | assert(object); | 12 | assert(object); |
13 | object->transform = mat4_id(); | ||
14 | } | ||
15 | 13 | ||
16 | SceneObject* gfx_make_object() { | 14 | bool first = true; |
17 | SceneObject* object = mem_alloc_object(); | 15 | aabb3 box; |
18 | scene_object_make(object); | ||
19 | return object; | ||
20 | } | ||
21 | 16 | ||
22 | void gfx_destroy_object(SceneObject** object) { | 17 | mesh_link_idx ml = object->mesh_link; |
23 | assert(object); | 18 | while (ml.val) { |
24 | if (*object) { | 19 | const MeshLink* mesh_link = mem_get_mesh_link(ml); |
25 | if ((*object)->parent.val) { | 20 | const mesh_idx mi = mesh_link->mesh; |
26 | gfx_del_node((*object)->parent); | 21 | if (mi.val) { |
22 | const Mesh* mesh = mem_get_mesh(mi); | ||
23 | const aabb3 mesh_box = gfx_get_geometry_aabb(mesh->geometry); | ||
24 | if (first) { | ||
25 | box = mesh_box; | ||
26 | first = false; | ||
27 | } else { | ||
28 | box = aabb3_sum(box, mesh_box); | ||
29 | } | ||
27 | } | 30 | } |
28 | mem_free_object(object); | 31 | ml = mesh_link->next; |
29 | } | 32 | } |
30 | } | ||
31 | 33 | ||
32 | void gfx_set_object_transform(SceneObject* object, const mat4* transform) { | 34 | return box; |
33 | assert(object); | ||
34 | assert(transform); | ||
35 | object->transform = *transform; | ||
36 | } | 35 | } |
37 | 36 | ||
38 | void gfx_add_object_mesh(SceneObject* object, Mesh* mesh) { | 37 | static void add_object_mesh(SceneObject* object, Mesh* mesh) { |
39 | assert(object); | 38 | assert(object); |
40 | assert(mesh); | 39 | assert(mesh); |
41 | 40 | ||
42 | MeshLink* link = mem_alloc_mesh_link(); | 41 | MeshLink* link = mem_alloc_mesh_link(); |
43 | assert(link); | ||
44 | link->mesh = mem_get_mesh_index(mesh); | 42 | link->mesh = mem_get_mesh_index(mesh); |
45 | link->next = object->mesh_link; | 43 | link->next = object->mesh_link; |
46 | object->mesh_link = mem_get_mesh_link_index(link); | 44 | object->mesh_link = mem_get_mesh_link_index(link); |
47 | } | 45 | } |
48 | 46 | ||
49 | void gfx_remove_object_mesh(SceneObject* object, Mesh* mesh) { | 47 | SceneObject* gfx_make_object(const ObjectDesc* desc) { |
50 | assert(object); | 48 | assert(desc); |
51 | assert(mesh); | 49 | |
50 | SceneObject* object = mem_alloc_object(); | ||
51 | for (size_t i = 0; i < desc->num_meshes; ++i) { | ||
52 | add_object_mesh(object, desc->meshes[i]); | ||
53 | } | ||
54 | object->box = calc_object_aabb(object); | ||
55 | return object; | ||
56 | } | ||
52 | 57 | ||
53 | MeshLink* prev = 0; | 58 | void gfx_destroy_object(SceneObject** object) { |
54 | const mesh_idx mesh_index = mem_get_mesh_index(mesh); | 59 | assert(object); |
55 | 60 | ||
56 | // Find the MeshLink in the object that contains the given mesh. | 61 | if (*object) { |
57 | for (mesh_link_idx mesh_link_index = object->mesh_link; | 62 | if ((*object)->parent.val) { |
58 | mesh_link_index.val;) { | 63 | gfx_del_node((*object)->parent); |
59 | MeshLink* mesh_link = mem_get_mesh_link(mesh_link_index); | ||
60 | if (mesh_link->mesh.val == mesh_index.val) { | ||
61 | if (prev) { | ||
62 | prev->next = mesh_link->next; | ||
63 | } else { | ||
64 | object->mesh_link = mesh_link->next; | ||
65 | } | ||
66 | mem_free_mesh_link(&mesh_link); | ||
67 | break; | ||
68 | } | 64 | } |
69 | prev = mesh_link; | 65 | mem_free_object(object); |
70 | mesh_link_index = mesh_link->next; | ||
71 | } | 66 | } |
72 | } | 67 | } |
73 | 68 | ||
@@ -77,31 +72,7 @@ void gfx_set_object_skeleton(SceneObject* object, const Skeleton* skeleton) { | |||
77 | object->skeleton = mem_get_skeleton_index(skeleton); | 72 | object->skeleton = mem_get_skeleton_index(skeleton); |
78 | } | 73 | } |
79 | 74 | ||
80 | // TODO: Could compute just once if we changed the Object API to require an | 75 | aabb3 gfx_get_object_aabb(const SceneObject* object) { |
81 | // object descriptor up front instead of allowing the client to add meshes | ||
82 | // and skeletons dynamically. | ||
83 | aabb3 gfx_calc_object_aabb(const SceneObject* object) { | ||
84 | assert(object); | 76 | assert(object); |
85 | 77 | return object->box; | |
86 | bool first = true; | ||
87 | aabb3 box; | ||
88 | |||
89 | mesh_link_idx ml = object->mesh_link; | ||
90 | while (ml.val) { | ||
91 | const MeshLink* mesh_link = mem_get_mesh_link(ml); | ||
92 | const mesh_idx mi = mesh_link->mesh; | ||
93 | if (mi.val) { | ||
94 | const Mesh* mesh = mem_get_mesh(mi); | ||
95 | const aabb3 mesh_box = gfx_get_geometry_aabb(mesh->geometry); | ||
96 | if (first) { | ||
97 | box = mesh_box; | ||
98 | first = false; | ||
99 | } else { | ||
100 | box = aabb3_sum(box, mesh_box); | ||
101 | } | ||
102 | } | ||
103 | ml = mesh_link->next; | ||
104 | } | ||
105 | |||
106 | return box; | ||
107 | } | 78 | } |
diff --git a/gfx/src/scene/object_impl.h b/gfx/src/scene/object_impl.h index 45119db..91e1427 100644 --- a/gfx/src/scene/object_impl.h +++ b/gfx/src/scene/object_impl.h | |||
@@ -19,8 +19,8 @@ typedef struct MeshLink { | |||
19 | /// different for each SceneObject. Each SceneObject may then have a unique list | 19 | /// different for each SceneObject. Each SceneObject may then have a unique list |
20 | /// of Meshes, and the Meshes are re-used. | 20 | /// of Meshes, and the Meshes are re-used. |
21 | typedef struct SceneObject { | 21 | typedef struct SceneObject { |
22 | mat4 transform; | 22 | mesh_link_idx mesh_link; /// First MeshLink in the list. |
23 | mesh_link_idx mesh_link; // First MeshLink in the list. | ||
24 | skeleton_idx skeleton; | 23 | skeleton_idx skeleton; |
25 | node_idx parent; // Parent SceneNode. | 24 | node_idx parent; /// Parent SceneNode. |
25 | aabb3 box; | ||
26 | } SceneObject; | 26 | } SceneObject; |
diff --git a/gfx/src/util/skyquad.c b/gfx/src/util/skyquad.c index d0f1cb0..5027705 100644 --- a/gfx/src/util/skyquad.c +++ b/gfx/src/util/skyquad.c | |||
@@ -56,11 +56,10 @@ SceneObject* gfx_make_skyquad( | |||
56 | goto cleanup; | 56 | goto cleanup; |
57 | } | 57 | } |
58 | 58 | ||
59 | object = gfx_make_object(); | 59 | object = gfx_make_object(&(ObjectDesc){.num_meshes = 1, .meshes = {mesh}}); |
60 | if (!object) { | 60 | if (!object) { |
61 | goto cleanup; | 61 | goto cleanup; |
62 | } | 62 | } |
63 | gfx_add_object_mesh(object, mesh); | ||
64 | 63 | ||
65 | return object; | 64 | return object; |
66 | 65 | ||