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 | ||
