1use crate::core::algebra::{Vector2, Vector3};
2use crate::{
3 core::pool::Handle,
4 resource::{
5 fbx::scene,
6 fbx::{
7 document::{FbxNode, FbxNodeContainer},
8 error::FbxError,
9 scene::{FbxComponent, FbxContainer, FbxScene},
10 },
11 },
12 scene::mesh::surface::{VertexWeight, VertexWeightSet},
13};
14
15pub struct FbxGeometry {
16 pub vertices: Vec<Vector3<f32>>,
18 pub indices: Vec<i32>,
19
20 pub normals: Option<FbxContainer<Vector3<f32>>>,
22 pub uvs: Option<FbxContainer<Vector2<f32>>>,
23 pub materials: Option<FbxContainer<i32>>,
24 pub tangents: Option<FbxContainer<Vector3<f32>>>,
25 pub binormals: Option<FbxContainer<Vector3<f32>>>,
26
27 pub deformers: Vec<Handle<FbxComponent>>,
28}
29
30fn read_vertices(
31 geom_node_handle: Handle<FbxNode>,
32 nodes: &FbxNodeContainer,
33) -> Result<Vec<Vector3<f32>>, FbxError> {
34 let vertices_node_handle = nodes.find(geom_node_handle, "Vertices")?;
35 let vertices_array_node = nodes.get_by_name(vertices_node_handle, "a")?;
36 let mut vertices = Vec::with_capacity(vertices_array_node.attrib_count() / 3);
37 for vertex in vertices_array_node.attributes().chunks_exact(3) {
38 vertices.push(Vector3::new(
39 vertex[0].as_f32()?,
40 vertex[1].as_f32()?,
41 vertex[2].as_f32()?,
42 ));
43 }
44
45 Ok(vertices)
46}
47
48fn read_indices(
49 geom_node_handle: Handle<FbxNode>,
50 nodes: &FbxNodeContainer,
51) -> Result<Vec<i32>, FbxError> {
52 let indices_node_handle = nodes.find(geom_node_handle, "PolygonVertexIndex")?;
53 let indices_array_node = nodes.get_by_name(indices_node_handle, "a")?;
54 let mut indices = Vec::with_capacity(indices_array_node.attrib_count());
55 for index in indices_array_node.attributes() {
56 indices.push(index.as_i32()?);
57 }
58 Ok(indices)
59}
60
61fn read_normals(
62 geom_node_handle: Handle<FbxNode>,
63 nodes: &FbxNodeContainer,
64) -> Result<Option<FbxContainer<Vector3<f32>>>, FbxError> {
65 if let Ok(layer_element_normal) = nodes.find(geom_node_handle, "LayerElementNormal") {
66 Ok(Some(scene::make_vec3_container(
67 nodes,
68 layer_element_normal,
69 "Normals",
70 )?))
71 } else {
72 Ok(None)
73 }
74}
75
76fn read_tangents(
77 geom_node_handle: Handle<FbxNode>,
78 nodes: &FbxNodeContainer,
79) -> Result<Option<FbxContainer<Vector3<f32>>>, FbxError> {
80 if let Ok(layer_element_tangent) = nodes.find(geom_node_handle, "LayerElementTangent") {
81 Ok(Some(scene::make_vec3_container(
82 nodes,
83 layer_element_tangent,
84 "Tangents",
85 )?))
86 } else {
87 Ok(None)
88 }
89}
90
91fn read_binormals(
92 geom_node_handle: Handle<FbxNode>,
93 nodes: &FbxNodeContainer,
94) -> Result<Option<FbxContainer<Vector3<f32>>>, FbxError> {
95 if let Ok(layer_element_tangent) = nodes.find(geom_node_handle, "LayerElementBinormal") {
96 Ok(Some(scene::make_vec3_container(
97 nodes,
98 layer_element_tangent,
99 "Binormals",
100 )?))
101 } else {
102 Ok(None)
103 }
104}
105
106fn read_uvs(
107 geom_node_handle: Handle<FbxNode>,
108 nodes: &FbxNodeContainer,
109) -> Result<Option<FbxContainer<Vector2<f32>>>, FbxError> {
110 if let Ok(layer_element_uv) = nodes.find(geom_node_handle, "LayerElementUV") {
111 Ok(Some(FbxContainer::new(
112 nodes,
113 layer_element_uv,
114 "UV",
115 |attributes| {
116 let mut uvs = Vec::with_capacity(attributes.len() / 2);
117 for uv in attributes.chunks_exact(2) {
118 uvs.push(Vector2::new(uv[0].as_f32()?, uv[1].as_f32()?));
119 }
120 Ok(uvs)
121 },
122 )?))
123 } else {
124 Ok(None)
125 }
126}
127
128fn read_materials(
129 geom_node_handle: Handle<FbxNode>,
130 nodes: &FbxNodeContainer,
131) -> Result<Option<FbxContainer<i32>>, FbxError> {
132 if let Ok(layer_element_material_node_handle) =
133 nodes.find(geom_node_handle, "LayerElementMaterial")
134 {
135 Ok(Some(FbxContainer::new(
136 nodes,
137 layer_element_material_node_handle,
138 "Materials",
139 |attributes| {
140 let mut materials = Vec::with_capacity(attributes.len());
141 for attribute in attributes {
142 materials.push(attribute.as_i32()?);
143 }
144 Ok(materials)
145 },
146 )?))
147 } else {
148 Ok(None)
149 }
150}
151
152impl FbxGeometry {
153 pub(in crate::resource::fbx) fn read(
154 geom_node_handle: Handle<FbxNode>,
155 nodes: &FbxNodeContainer,
156 ) -> Result<FbxGeometry, FbxError> {
157 Ok(FbxGeometry {
158 vertices: read_vertices(geom_node_handle, nodes)?,
159 indices: read_indices(geom_node_handle, nodes)?,
160 normals: read_normals(geom_node_handle, nodes)?,
161 uvs: read_uvs(geom_node_handle, nodes)?,
162 materials: read_materials(geom_node_handle, nodes)?,
163 tangents: read_tangents(geom_node_handle, nodes)?,
164 binormals: read_binormals(geom_node_handle, nodes)?,
165 deformers: Vec::new(),
166 })
167 }
168
169 pub(in crate::resource::fbx) fn get_skin_data(
170 &self,
171 scene: &FbxScene,
172 ) -> Result<Vec<VertexWeightSet>, FbxError> {
173 let mut out = vec![VertexWeightSet::default(); self.vertices.len()];
174 for &deformer_handle in self.deformers.iter() {
175 for &sub_deformer_handle in scene
176 .get(deformer_handle)
177 .as_deformer()?
178 .sub_deformers
179 .iter()
180 {
181 let sub_deformer = scene.get(sub_deformer_handle).as_sub_deformer()?;
182 for (index, weight) in sub_deformer.weights.iter() {
183 let bone_set = out
184 .get_mut(*index as usize)
185 .ok_or(FbxError::IndexOutOfBounds)?;
186 if !bone_set.push(VertexWeight {
187 value: *weight,
188 effector: sub_deformer.model.into(),
189 }) {
190 bone_set.normalize();
192 }
193 }
194 }
195 }
196 Ok(out)
197 }
198}