diff options
-rw-r--r-- | game/src/plugins/viewer.c | 8 | ||||
-rw-r--r-- | gfx/include/gfx/asset.h | 14 | ||||
-rw-r--r-- | gfx/include/gfx/scene/node.h | 2 | ||||
-rw-r--r-- | gfx/include/gfx/util/scene.h | 10 | ||||
-rw-r--r-- | gfx/src/asset/asset_cache.c | 4 | ||||
-rw-r--r-- | gfx/src/scene/node.c | 4 | ||||
-rw-r--r-- | gfx/src/util/scene.c | 65 |
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. | ||
71 | typedef struct LoadSceneCmd { | 75 | typedef 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. |
95 | SceneNode* gfx_load_scene(Gfx*, SceneNode* root_node, const LoadSceneCmd*); | 97 | SceneNode* gfx_load_scene(Gfx*, SceneNode* parent_node, const LoadSceneCmd*); |
96 | 98 | ||
97 | /// Load a texture. | 99 | /// Load a texture. |
98 | Texture* gfx_load_texture(Gfx*, const LoadTextureCmd*); | 100 | Texture* 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. |
141 | void gfx_set_node_parent(SceneNode*, SceneNode* parent); | 141 | void gfx_set_node_parent(SceneNode*, SceneNode* parent_node); |
142 | 142 | ||
143 | /// Set the node's (local) transform. | 143 | /// Set the node's (local) transform. |
144 | void gfx_set_node_transform(SceneNode*, const mat4* transform); | 144 | void 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. |
19 | SceneNode* gfx_scene_load(Gfx*, SceneNode* root_node, const LoadSceneCmd*); | 17 | SceneNode* 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 | ||
115 | SceneNode* gfx_load_scene( | 115 | SceneNode* 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 | ||
274 | void gfx_set_node_parent(SceneNode* child, SceneNode* parent) { | 274 | void 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 | ||
280 | void gfx_set_node_transform(SceneNode* node, const mat4* transform) { | 280 | void 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. |
1408 | static SceneNode* load_scene( | 1409 | static 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 | ||
1531 | cleanup: | 1540 | cleanup: |
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 | ||
1638 | SceneNode* gfx_scene_load( | 1649 | SceneNode* 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 | ||
1680 | cleanup: | 1691 | cleanup: |