diff options
-rw-r--r-- | gfx/src/asset/model.c | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/gfx/src/asset/model.c b/gfx/src/asset/model.c index 73ce731..05e6e91 100644 --- a/gfx/src/asset/model.c +++ b/gfx/src/asset/model.c | |||
@@ -986,7 +986,7 @@ static bool load_meshes( | |||
986 | const cgltf_buffer_view* view = accessor->buffer_view; | 986 | const cgltf_buffer_view* view = accessor->buffer_view; |
987 | const cgltf_size offset = accessor->offset + view->offset; | 987 | const cgltf_size offset = accessor->offset + view->offset; |
988 | const cgltf_size buffer_index = view->buffer - data->buffers; | 988 | const cgltf_size buffer_index = view->buffer - data->buffers; |
989 | 989 | ||
990 | assert(buffer_index < data->buffers_count); | 990 | assert(buffer_index < data->buffers_count); |
991 | Buffer* buffer = buffers[buffer_index]; | 991 | Buffer* buffer = buffers[buffer_index]; |
992 | 992 | ||
@@ -1492,6 +1492,66 @@ static void load_nodes( | |||
1492 | } // SceneNode. | 1492 | } // SceneNode. |
1493 | } | 1493 | } |
1494 | 1494 | ||
1495 | /// Remove joint nodes from the Gfx Scene. | ||
1496 | /// | ||
1497 | /// Joint nodes are not needed because joints are packed into the Anima. | ||
1498 | static void remove_joint_nodes( | ||
1499 | const cgltf_data* data, SceneNode** scene_nodes) { | ||
1500 | assert(data); | ||
1501 | assert(scene_nodes); | ||
1502 | |||
1503 | // This works assuming the joint nodes are contiguous. Contiguity is checked | ||
1504 | // when loading skins. See load_skins(). | ||
1505 | size_t min_joint_index = (size_t)-1; | ||
1506 | size_t max_joint_index = 0; | ||
1507 | |||
1508 | // First get the minimum and maximum indices of all joint nodes. | ||
1509 | for (cgltf_size s = 0; s < data->skins_count; ++s) { | ||
1510 | const cgltf_skin* skin = &data->skins[s]; | ||
1511 | |||
1512 | for (cgltf_size j = 0; j < skin->joints_count; ++j) { | ||
1513 | // Joint is an index/pointer into the nodes array. | ||
1514 | const cgltf_size joint_index = skin->joints[j] - data->nodes; | ||
1515 | assert(joint_index < data->nodes_count); | ||
1516 | |||
1517 | if (joint_index < min_joint_index) { | ||
1518 | min_joint_index = joint_index; | ||
1519 | } | ||
1520 | if (joint_index > max_joint_index) { | ||
1521 | max_joint_index = joint_index; | ||
1522 | } | ||
1523 | } | ||
1524 | } | ||
1525 | |||
1526 | assert(min_joint_index < data->nodes_count); | ||
1527 | assert(max_joint_index < data->nodes_count); | ||
1528 | |||
1529 | // Now walk over the joint nodes. If a joint's parent is itself not a joint | ||
1530 | // node, then that joint is a root of a joint hierarchy (skins in glTF may | ||
1531 | // have multiple roots). In such case, delete the root joint recursively. | ||
1532 | for (cgltf_size s = 0; s < data->skins_count; ++s) { | ||
1533 | const cgltf_skin* skin = &data->skins[s]; | ||
1534 | |||
1535 | for (cgltf_size j = 0; j < skin->joints_count; ++j) { | ||
1536 | // Joint is an index/pointer into the nodes array. | ||
1537 | const cgltf_size joint_index = skin->joints[j] - data->nodes; | ||
1538 | assert(joint_index < data->nodes_count); | ||
1539 | |||
1540 | const cgltf_node* joint = &data->nodes[joint_index]; | ||
1541 | |||
1542 | // Parent node index. | ||
1543 | const cgltf_size parent_index = joint->parent - data->nodes; | ||
1544 | assert(parent_index < data->nodes_count); | ||
1545 | |||
1546 | // If the parent is not a joint node, recursively delete this joint node. | ||
1547 | if ((parent_index < min_joint_index) || | ||
1548 | (parent_index > max_joint_index)) { | ||
1549 | gfx_destroy_node(&scene_nodes[joint_index]); | ||
1550 | } | ||
1551 | } | ||
1552 | } | ||
1553 | } | ||
1554 | |||
1495 | /// Load all scenes from the glTF file. | 1555 | /// Load all scenes from the glTF file. |
1496 | /// | 1556 | /// |
1497 | /// If the scene is loaded from memory, set filepath = null. | 1557 | /// If the scene is loaded from memory, set filepath = null. |
@@ -1629,7 +1689,11 @@ static Model* load_scene( | |||
1629 | // The root node becomes the root of all scene nodes. | 1689 | // The root node becomes the root of all scene nodes. |
1630 | load_nodes(data, root_node, scene_objects, scene_cameras, anima, scene_nodes); | 1690 | load_nodes(data, root_node, scene_objects, scene_cameras, anima, scene_nodes); |
1631 | 1691 | ||
1632 | // TODO: Clean up scene nodes that correspond to joints in the glTF. | 1692 | // Clean up scene nodes that correspond to joints in the glTF. These are |
1693 | // not needed anymore. | ||
1694 | if (data->skins_count > 0) { | ||
1695 | remove_joint_nodes(data, scene_nodes); | ||
1696 | } | ||
1633 | 1697 | ||
1634 | model = gfx_make_model(root_node); | 1698 | model = gfx_make_model(root_node); |
1635 | 1699 | ||