Skip to main content

gltforge_unity/
unity_submesh.rs

1use crate::unity_gltf::UnityGltf;
2
3use gltforge_unity_core::UnityIndices;
4
5/// Return the number of sub-meshes in mesh `mesh_idx`.
6///
7/// # Safety
8/// `ptr` must be a valid, non-null handle.
9#[unsafe(no_mangle)]
10pub unsafe extern "C" fn gltforge_mesh_submesh_count(ptr: *const UnityGltf, mesh_idx: u32) -> u32 {
11    unsafe { &*ptr }
12        .meshes
13        .get(&mesh_idx)
14        .map(|m| m.sub_meshes.len() as u32)
15        .unwrap_or(0)
16}
17
18/// Return a pointer to the `u16` index data for sub-mesh `submesh` of mesh `mesh_idx`.
19/// Returns null if the mesh uses `u32` indices or the indices are out of range.
20/// `out_len` receives the number of index values (not bytes).
21///
22/// # Safety
23/// `ptr` must be a valid, non-null handle. `out_len` may be null.
24#[unsafe(no_mangle)]
25pub unsafe extern "C" fn gltforge_mesh_submesh_indices_u16(
26    ptr: *const UnityGltf,
27    mesh_idx: u32,
28    submesh: u32,
29    out_len: *mut u32,
30) -> *const u16 {
31    let gltf = unsafe { &*ptr };
32    match gltf
33        .meshes
34        .get(&mesh_idx)
35        .and_then(|m| m.sub_meshes.get(submesh as usize))
36        .map(|s| &s.indices)
37    {
38        Some(UnityIndices::U16(v)) => {
39            if !out_len.is_null() {
40                unsafe { *out_len = v.len() as u32 };
41            }
42            v.as_ptr()
43        }
44        _ => {
45            if !out_len.is_null() {
46                unsafe { *out_len = 0 };
47            }
48            std::ptr::null()
49        }
50    }
51}
52
53/// Return a pointer to the `u32` index data for sub-mesh `submesh` of mesh `mesh_idx`.
54/// Returns null if the mesh uses `u16` indices or the indices are out of range.
55/// `out_len` receives the number of index values (not bytes).
56///
57/// # Safety
58/// `ptr` must be a valid, non-null handle. `out_len` may be null.
59#[unsafe(no_mangle)]
60pub unsafe extern "C" fn gltforge_mesh_submesh_indices_u32(
61    ptr: *const UnityGltf,
62    mesh_idx: u32,
63    submesh: u32,
64    out_len: *mut u32,
65) -> *const u32 {
66    let gltf = unsafe { &*ptr };
67    match gltf
68        .meshes
69        .get(&mesh_idx)
70        .and_then(|m| m.sub_meshes.get(submesh as usize))
71        .map(|s| &s.indices)
72    {
73        Some(UnityIndices::U32(v)) => {
74            if !out_len.is_null() {
75                unsafe { *out_len = v.len() as u32 };
76            }
77            v.as_ptr()
78        }
79        _ => {
80            if !out_len.is_null() {
81                unsafe { *out_len = 0 };
82            }
83            std::ptr::null()
84        }
85    }
86}
87
88/// Return the `GLTF/PbrMetallicRoughness` material index for sub-mesh `submesh` of mesh
89/// `mesh_idx`, or `-1` if the primitive had no material.
90///
91/// # Safety
92/// `ptr` must be a valid, non-null handle.
93#[unsafe(no_mangle)]
94pub unsafe extern "C" fn gltforge_mesh_submesh_material(
95    ptr: *const UnityGltf,
96    mesh_idx: u32,
97    submesh: u32,
98) -> i32 {
99    unsafe { &*ptr }
100        .meshes
101        .get(&mesh_idx)
102        .and_then(|m| m.sub_meshes.get(submesh as usize))
103        .and_then(|s| s.material_index)
104        .map_or(-1, |i| i as i32)
105}