summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2024-02-13 18:27:18 -0800
committer3gg <3gg@shellblade.net>2024-02-13 18:27:18 -0800
commitf03ee01bc593ad2271f697bf286ebc04c91da0b1 (patch)
treef6036a15465718d68a5f5c3996d619e4bea61247
parent090f91787b3f4e4711e4aada5ffc232d984b8ce1 (diff)
Make loaded scene node an anima node only if the scene has skins/skeletons.
-rw-r--r--game/src/plugins/viewer.c8
-rw-r--r--gfx/include/gfx/asset.h14
-rw-r--r--gfx/include/gfx/scene/node.h2
-rw-r--r--gfx/include/gfx/util/scene.h10
-rw-r--r--gfx/src/asset/asset_cache.c4
-rw-r--r--gfx/src/scene/node.c4
-rw-r--r--gfx/src/util/scene.c65
7 files changed, 60 insertions, 47 deletions
diff --git a/game/src/plugins/viewer.c b/game/src/plugins/viewer.c
index 3000b30..769887f 100644
--- a/game/src/plugins/viewer.c
+++ b/game/src/plugins/viewer.c
@@ -120,9 +120,11 @@ bool init(Game* game, State** pp_state) {
120 goto cleanup; 120 goto cleanup;
121 } 121 }
122 122
123 Anima* anima = gfx_get_node_anima(node); 123 if (gfx_get_node_type(node) == AnimaNode) {
124 gfx_play_animation( 124 Anima* anima = gfx_get_node_anima(node);
125 anima, &(AnimationPlaySettings){.name = "Walk", .loop = true}); 125 gfx_play_animation(
126 anima, &(AnimationPlaySettings){.name = "Walk", .loop = true});
127 }
126 128
127 *pp_state = state; 129 *pp_state = state;
128 return true; 130 return true;
diff --git a/gfx/include/gfx/asset.h b/gfx/include/gfx/asset.h
index 28b8557..c2bac57 100644
--- a/gfx/include/gfx/asset.h
+++ b/gfx/include/gfx/asset.h
@@ -68,6 +68,10 @@ typedef struct LoadTextureCmd {
68} LoadTextureCmd; 68} LoadTextureCmd;
69 69
70/// Describes a command to load a scene. 70/// Describes a command to load a scene.
71///
72/// |shader| is an optional shader program assigned to the loaded scene objects.
73/// If no shader is given, a Cook-Torrance shader based on the object's
74/// characteristics (presence of normals, tangents, etc) is assigned.
71typedef struct LoadSceneCmd { 75typedef struct LoadSceneCmd {
72 AssetOrigin origin; 76 AssetOrigin origin;
73 union { 77 union {
@@ -84,15 +88,13 @@ typedef struct LoadSceneCmd {
84 88
85/// Load a scene. 89/// Load a scene.
86/// 90///
87/// Return a top-level node under which scene elements are rooted. |root_node| 91/// Return a top-level node under which scene elements are rooted.
88/// is made the parent of this top-level node.
89/// 92///
90/// |shader| is an optional shader program assigned to the loaded scene objects. 93/// |parent_node| is made the parent of the returned top-level node. It may be
91/// If no shader is given, a Cook-Torrance shader based on the object's 94/// null.
92/// characteristics (presence of normals, tangents, etc) is assigned.
93/// 95///
94/// Currently only supports the GLTF format. 96/// Currently only supports the GLTF format.
95SceneNode* gfx_load_scene(Gfx*, SceneNode* root_node, const LoadSceneCmd*); 97SceneNode* gfx_load_scene(Gfx*, SceneNode* parent_node, const LoadSceneCmd*);
96 98
97/// Load a texture. 99/// Load a texture.
98Texture* gfx_load_texture(Gfx*, const LoadTextureCmd*); 100Texture* gfx_load_texture(Gfx*, const LoadTextureCmd*);
diff --git a/gfx/include/gfx/scene/node.h b/gfx/include/gfx/scene/node.h
index 9507392..aedac92 100644
--- a/gfx/include/gfx/scene/node.h
+++ b/gfx/include/gfx/scene/node.h
@@ -138,7 +138,7 @@ mat4 gfx_get_node_global_transform(const SceneNode*);
138/// Set the node's parent. 138/// Set the node's parent.
139/// 139///
140/// Pass in null to unwire from the existing parent, if one exists. 140/// Pass in null to unwire from the existing parent, if one exists.
141void gfx_set_node_parent(SceneNode*, SceneNode* parent); 141void gfx_set_node_parent(SceneNode*, SceneNode* parent_node);
142 142
143/// Set the node's (local) transform. 143/// Set the node's (local) transform.
144void gfx_set_node_transform(SceneNode*, const mat4* transform); 144void gfx_set_node_transform(SceneNode*, const mat4* transform);
diff --git a/gfx/include/gfx/util/scene.h b/gfx/include/gfx/util/scene.h
index c03e2cb..5c47196 100644
--- a/gfx/include/gfx/util/scene.h
+++ b/gfx/include/gfx/util/scene.h
@@ -8,12 +8,10 @@ typedef struct SceneNode SceneNode;
8 8
9/// Load a scene. 9/// Load a scene.
10/// 10///
11/// Return a top-level node under which scene elements are rooted. |root_node| 11/// Return the top-level node under which scene elements are rooted.
12/// is made the parent of this top-level node.
13/// 12///
14/// |shader| is an optional shader program assigned to the loaded scene objects. 13/// |parent_node| is made the parent of the returned top-level node. It may be
15/// If no shader is given, a Cook-Torrance shader based on the object's 14/// null.
16/// characteristics (presence of normals, tangents, etc) is assigned.
17/// 15///
18/// Currently only supports the GLTF format. 16/// Currently only supports the GLTF format.
19SceneNode* gfx_scene_load(Gfx*, SceneNode* root_node, const LoadSceneCmd*); 17SceneNode* gfx_scene_load(Gfx*, SceneNode* parent_node, const LoadSceneCmd*);
diff --git a/gfx/src/asset/asset_cache.c b/gfx/src/asset/asset_cache.c
index 2fa57ad..fd9f1f8 100644
--- a/gfx/src/asset/asset_cache.c
+++ b/gfx/src/asset/asset_cache.c
@@ -113,7 +113,7 @@ void gfx_destroy_asset_cache(AssetCache* cache) {
113} 113}
114 114
115SceneNode* gfx_load_scene( 115SceneNode* gfx_load_scene(
116 Gfx* gfx, SceneNode* root_node, const LoadSceneCmd* cmd) { 116 Gfx* gfx, SceneNode* parent_node, const LoadSceneCmd* cmd) {
117 assert(gfx); 117 assert(gfx);
118 118
119 AssetCache* cache = gfx_get_asset_cache(gfx); 119 AssetCache* cache = gfx_get_asset_cache(gfx);
@@ -130,7 +130,7 @@ SceneNode* gfx_load_scene(
130 130
131 // Asset not found in the cache. 131 // Asset not found in the cache.
132 // Load it, insert it into the cache, and return it. 132 // Load it, insert it into the cache, and return it.
133 SceneNode* node = gfx_scene_load(gfx, root_node, cmd); 133 SceneNode* node = gfx_scene_load(gfx, parent_node, cmd);
134 if (node) { 134 if (node) {
135 *(Asset*)mempool_alloc(&cache->assets) = (Asset){ 135 *(Asset*)mempool_alloc(&cache->assets) = (Asset){
136 .type = SceneAsset, 136 .type = SceneAsset,
diff --git a/gfx/src/scene/node.c b/gfx/src/scene/node.c
index 2f761a2..333dc28 100644
--- a/gfx/src/scene/node.c
+++ b/gfx/src/scene/node.c
@@ -271,10 +271,10 @@ mat4 gfx_get_node_global_transform(const SceneNode* node) {
271 return transform; 271 return transform;
272} 272}
273 273
274void gfx_set_node_parent(SceneNode* child, SceneNode* parent) { 274void gfx_set_node_parent(SceneNode* child, SceneNode* parent_node) {
275 assert(child); 275 assert(child);
276 // Parent can be null. 276 // Parent can be null.
277 SET_PARENT(child, parent); 277 SET_PARENT(child, parent_node);
278} 278}
279 279
280void gfx_set_node_transform(SceneNode* node, const mat4* transform) { 280void gfx_set_node_transform(SceneNode* node, const mat4* transform) {
diff --git a/gfx/src/util/scene.c b/gfx/src/util/scene.c
index 5bf45aa..a491238 100644
--- a/gfx/src/util/scene.c
+++ b/gfx/src/util/scene.c
@@ -1303,7 +1303,6 @@ static void load_nodes(
1303 assert(root_node); 1303 assert(root_node);
1304 assert(objects); 1304 assert(objects);
1305 assert(cameras); 1305 assert(cameras);
1306 assert(anima);
1307 assert(nodes); 1306 assert(nodes);
1308 1307
1309 cgltf_size next_camera = 0; 1308 cgltf_size next_camera = 0;
@@ -1320,6 +1319,8 @@ static void load_nodes(
1320 1319
1321 gfx_construct_object_node(nodes[n], object); 1320 gfx_construct_object_node(nodes[n], object);
1322 if (node->skin) { 1321 if (node->skin) {
1322 assert(anima);
1323
1323 const cgltf_size skin_index = node->skin - data->skins; 1324 const cgltf_size skin_index = node->skin - data->skins;
1324 assert(skin_index < data->skins_count); 1325 assert(skin_index < data->skins_count);
1325 const Skeleton* skeleton = gfx_get_anima_skeleton(anima, skin_index); 1326 const Skeleton* skeleton = gfx_get_anima_skeleton(anima, skin_index);
@@ -1406,7 +1407,7 @@ static void load_nodes(
1406/// This function ignores the many scenes and default scene of the glTF spec 1407/// This function ignores the many scenes and default scene of the glTF spec
1407/// and instead just loads all scenes into a single gfx Scene. 1408/// and instead just loads all scenes into a single gfx Scene.
1408static SceneNode* load_scene( 1409static SceneNode* load_scene(
1409 cgltf_data* data, Gfx* gfx, SceneNode* root_node, const mstring* filepath, 1410 cgltf_data* data, Gfx* gfx, SceneNode* parent_node, const mstring* filepath,
1410 ShaderProgram* shader, const cgltfTangentBuffer* cgltf_tangent_buffers, 1411 ShaderProgram* shader, const cgltfTangentBuffer* cgltf_tangent_buffers,
1411 cgltf_size num_tangent_buffers) { 1412 cgltf_size num_tangent_buffers) {
1412 // In a GLTF scene, buffers can be shared among meshes, meshes among nodes, 1413 // In a GLTF scene, buffers can be shared among meshes, meshes among nodes,
@@ -1427,7 +1428,8 @@ static SceneNode* load_scene(
1427 // stage. 1428 // stage.
1428 assert(data); 1429 assert(data);
1429 assert(gfx); 1430 assert(gfx);
1430 assert(root_node); 1431 assert(filepath);
1432 assert((num_tangent_buffers == 0) || (cgltf_tangent_buffers != 0));
1431 1433
1432 bool success = false; 1434 bool success = false;
1433 1435
@@ -1450,7 +1452,7 @@ static SceneNode* load_scene(
1450 SceneCamera** scene_cameras = 0; 1452 SceneCamera** scene_cameras = 0;
1451 SceneNode** scene_nodes = 0; 1453 SceneNode** scene_nodes = 0;
1452 Anima* anima = 0; 1454 Anima* anima = 0;
1453 SceneNode* anima_node = 0; 1455 SceneNode* root_node = 0;
1454 1456
1455 tangent_buffers = calloc(num_tangent_buffers, sizeof(Buffer*)); 1457 tangent_buffers = calloc(num_tangent_buffers, sizeof(Buffer*));
1456 buffers = calloc(data->buffers_count, sizeof(Buffer*)); 1458 buffers = calloc(data->buffers_count, sizeof(Buffer*));
@@ -1458,7 +1460,6 @@ static SceneNode* load_scene(
1458 materials = calloc(data->materials_count, sizeof(Material*)); 1460 materials = calloc(data->materials_count, sizeof(Material*));
1459 geometries = calloc(primitive_count, sizeof(Geometry*)); 1461 geometries = calloc(primitive_count, sizeof(Geometry*));
1460 meshes = calloc(primitive_count, sizeof(Mesh*)); 1462 meshes = calloc(primitive_count, sizeof(Mesh*));
1461 anima_desc = calloc(1, sizeof(AnimaDesc));
1462 scene_objects = calloc(data->meshes_count, sizeof(SceneObject*)); 1463 scene_objects = calloc(data->meshes_count, sizeof(SceneObject*));
1463 scene_cameras = calloc(data->cameras_count, sizeof(SceneCamera**)); 1464 scene_cameras = calloc(data->cameras_count, sizeof(SceneCamera**));
1464 scene_nodes = calloc(data->nodes_count, sizeof(SceneNode**)); 1465 scene_nodes = calloc(data->nodes_count, sizeof(SceneNode**));
@@ -1511,22 +1512,30 @@ static SceneNode* load_scene(
1511 scene_nodes[i] = gfx_make_node(); 1512 scene_nodes[i] = gfx_make_node();
1512 } 1513 }
1513 1514
1514 // TODO: If the scene does not have animations, then a top-level LogicalNode 1515 // Create the scene's root node.
1515 // would make more sense than an AnimaNode. 1516 // This is an anima node if the scene has skins; otherwise it is a logical
1516 anima_node = gfx_make_node(); 1517 // node.
1517 load_skins(data, buffers, scene_nodes, anima_desc->skeletons); 1518 root_node = gfx_make_node();
1518 load_animations(data, scene_nodes, anima_desc->animations); 1519 if (data->skins_count > 0) {
1519 anima_desc->num_skeletons = data->skins_count; 1520 anima_desc = calloc(1, sizeof(AnimaDesc));
1520 anima_desc->num_animations = data->animations_count; 1521 if (!anima_desc) {
1521 anima = gfx_make_anima(anima_desc); 1522 goto cleanup;
1522 gfx_construct_anima_node(anima_node, anima); 1523 }
1523 gfx_set_node_parent(anima_node, root_node); 1524
1525 load_skins(data, buffers, scene_nodes, anima_desc->skeletons);
1526 load_animations(data, scene_nodes, anima_desc->animations);
1524 1527
1525 // The anima node becomes the root of all scene nodes. 1528 anima_desc->num_skeletons = data->skins_count;
1526 load_nodes( 1529 anima_desc->num_animations = data->animations_count;
1527 data, anima_node, scene_objects, scene_cameras, anima, scene_nodes); 1530 anima = gfx_make_anima(anima_desc);
1531 gfx_construct_anima_node(root_node, anima);
1532 }
1533 gfx_set_node_parent(root_node, parent_node);
1534
1535 // The root node becomes the root of all scene nodes.
1536 load_nodes(data, root_node, scene_objects, scene_cameras, anima, scene_nodes);
1528 1537
1529 success = anima_node != 0; 1538 success = true;
1530 1539
1531cleanup: 1540cleanup:
1532 // The arrays of resources are no longer needed. The resources themselves are 1541 // The arrays of resources are no longer needed. The resources themselves are
@@ -1627,18 +1636,20 @@ cleanup:
1627 } 1636 }
1628 free(scene_nodes); 1637 free(scene_nodes);
1629 } 1638 }
1630 if (!success && anima_node) { 1639 if (!success) {
1631 gfx_destroy_node(&anima_node); // Node owns the anima. 1640 if (root_node) {
1632 } else if (!success && anima) { 1641 gfx_destroy_node(&root_node); // Node owns the anima.
1633 gfx_destroy_anima(&anima); 1642 } else if (anima) {
1643 gfx_destroy_anima(&anima);
1644 }
1634 } 1645 }
1635 return anima_node; 1646 return root_node;
1636} 1647}
1637 1648
1638SceneNode* gfx_scene_load( 1649SceneNode* gfx_scene_load(
1639 Gfx* gfx, SceneNode* root_node, const LoadSceneCmd* cmd) { 1650 Gfx* gfx, SceneNode* parent_node, const LoadSceneCmd* cmd) {
1640 assert(gfx); 1651 assert(gfx);
1641 assert(root_node); 1652 assert(parent_node);
1642 assert(cmd); 1653 assert(cmd);
1643 1654
1644 SceneNode* scene_node = 0; 1655 SceneNode* scene_node = 0;
@@ -1674,7 +1685,7 @@ SceneNode* gfx_scene_load(
1674 &options, data, &tangent_buffers, &num_tangent_buffers); 1685 &options, data, &tangent_buffers, &num_tangent_buffers);
1675 1686
1676 scene_node = load_scene( 1687 scene_node = load_scene(
1677 data, gfx, root_node, &cmd->filepath, cmd->shader, tangent_buffers, 1688 data, gfx, parent_node, &cmd->filepath, cmd->shader, tangent_buffers,
1678 num_tangent_buffers); 1689 num_tangent_buffers);
1679 1690
1680cleanup: 1691cleanup: