1use super::*;
2
3#[derive(Default)]
9pub(super) struct Scene<'a> {
10 pub(super) instance_visual_scene: Option<InstanceVisualScene<'a>>,
11}
12
13pub(super) struct InstanceVisualScene<'a> {
19 pub(super) url: Uri<'a, Node<'a>>,
25}
26
27#[derive(Default)]
33pub(super) struct LibraryVisualScenes<'a> {
34 pub(super) nodes: Vec<Node<'a>>,
39}
40
41#[derive(Default)]
47pub(super) struct Node<'a> {
48 pub(super) id: Option<&'a str>,
50 pub(super) parent: Option<usize>,
57 pub(super) transform: Matrix4x4,
60 pub(super) instance_geometry: Vec<InstanceGeometry<'a>>,
63 }
66
67#[derive(Debug)]
69pub(super) enum NodeType {
70 Joint,
71 Node,
72}
73
74impl Default for NodeType {
75 fn default() -> Self {
76 Self::Node
77 }
78}
79
80pub(super) enum Transform {
81 Lookat([f32; 9]),
82 Rotate([f32; 4]),
83 Translate([f32; 3]),
84 Scale([f32; 3]),
85 Skew(#[allow(dead_code)] [f32; 7]),
86 Matrix([f32; 16]),
87}
88
89impl Transform {
90 fn calculate_transform(transforms: &[Self]) -> Matrix4x4 {
92 fn sub(mut a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
94 a[0] -= b[0];
95 a[1] -= b[1];
96 a[2] -= b[2];
97 a
98 }
99 fn cross_product(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
100 let mut r = [0.; 3];
101 r[0] = a[1] * b[2] - a[2] * b[1];
102 r[1] = a[2] * b[0] - a[0] * b[2];
103 r[2] = a[0] * b[1] - a[1] * b[0];
104 r
105 }
106 fn normalize(mut v: [f32; 3]) -> [f32; 3] {
107 let square_len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
108 let len = square_len.sqrt();
109 if len == 0. {
110 return v;
111 }
112 let inv = 1. / len;
113 v[0] *= inv;
114 v[1] *= inv;
115 v[2] *= inv;
116 v
117 }
118
119 let mut out = None;
120 for transform in transforms {
121 match transform {
122 Self::Lookat(f) => {
123 let pos = [f[0], f[1], f[2]];
124 let dst_pos = [f[3], f[4], f[5]];
125 let up = normalize([f[6], f[7], f[8]]);
126 let dir = normalize(sub(dst_pos, pos));
127 let right = normalize(cross_product(dir, up));
128 let m = Matrix4x4::new(
129 right[0], up[0], -dir[0], pos[0], right[1], up[1], -dir[1], pos[1],
130 right[2], up[2], -dir[2], pos[2], 0., 0., 0., 1.,
131 );
132 match &mut out {
133 Some(out) => *out *= m,
134 _ => out = Some(m),
135 }
136 }
137 Self::Rotate(f) => {
138 let angle = f[3].to_radians();
139 let axis = [f[0], f[1], f[2]];
140 let m = Matrix4x4::rotation(angle, axis);
141 match &mut out {
142 Some(out) => *out *= m,
143 _ => out = Some(m),
144 }
145 }
146 Self::Translate(f) => {
147 let m = Matrix4x4::translation(*f);
148 match &mut out {
149 Some(out) => *out *= m,
150 _ => out = Some(m),
151 }
152 }
153 Self::Scale(f) => {
154 let m = Matrix4x4::new(
155 f[0], 0., 0., 0., 0., f[1], 0., 0., 0., 0., f[2], 0., 0., 0., 0., 1.,
156 );
157 match &mut out {
158 Some(out) => *out *= m,
159 _ => out = Some(m),
160 }
161 }
162 Self::Skew(_f) => {
163 }
165 Self::Matrix(f) => {
166 let m = Matrix4x4::new(
167 f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9], f[10], f[11],
168 f[12], f[13], f[14], f[15],
169 );
170 match &mut out {
171 Some(out) => *out *= m,
172 _ => out = Some(m),
173 }
174 }
175 }
176 }
177 out.unwrap_or_default()
178 }
179}
180
181#[derive(Clone, Copy)]
183pub(super) struct Matrix4x4 {
184 a1: f32,
185 a2: f32,
186 a3: f32,
187 a4: f32,
188 b1: f32,
189 b2: f32,
190 b3: f32,
191 b4: f32,
192 c1: f32,
193 c2: f32,
194 c3: f32,
195 c4: f32,
196 d1: f32,
197 d2: f32,
198 d3: f32,
199 d4: f32,
200}
201impl Matrix4x4 {
202 pub(super) const fn new(
203 a1: f32,
204 a2: f32,
205 a3: f32,
206 a4: f32,
207 b1: f32,
208 b2: f32,
209 b3: f32,
210 b4: f32,
211 c1: f32,
212 c2: f32,
213 c3: f32,
214 c4: f32,
215 d1: f32,
216 d2: f32,
217 d3: f32,
218 d4: f32,
219 ) -> Self {
220 Self {
221 a1,
222 a2,
223 a3,
224 a4,
225 b1,
226 b2,
227 b3,
228 b4,
229 c1,
230 c2,
231 c3,
232 c4,
233 d1,
234 d2,
235 d3,
236 d4,
237 }
238 }
239 fn rotation(a: f32, axis: [f32; 3]) -> Self {
240 let c = a.cos();
241 let s = a.sin();
242 let t = 1. - c;
243 let [x, y, z] = axis;
244 Self::new(
245 t * x * x + c,
246 t * x * y - s * z,
247 t * x * z + s * y,
248 0.,
249 t * x * y + s * z,
250 t * y * y + c,
251 t * y * z - s * x,
252 0.,
253 t * x * z - s * y,
254 t * y * z + s * x,
255 t * z * z + c,
256 0.,
257 0.,
258 0.,
259 0.,
260 1.,
261 )
262 }
263 fn translation(v: [f32; 3]) -> Self {
264 Self {
265 a4: v[0],
266 b4: v[1],
267 c4: v[2],
268 ..Default::default()
269 }
270 }
271 pub(super) fn is_identity(&self) -> bool {
272 const EPSILON: f32 = 10e-3;
274 self.a2 <= EPSILON
275 && self.a2 >= -EPSILON
276 && self.a3 <= EPSILON
277 && self.a3 >= -EPSILON
278 && self.a4 <= EPSILON
279 && self.a4 >= -EPSILON
280 && self.b1 <= EPSILON
281 && self.b1 >= -EPSILON
282 && self.b3 <= EPSILON
283 && self.b3 >= -EPSILON
284 && self.b4 <= EPSILON
285 && self.b4 >= -EPSILON
286 && self.c1 <= EPSILON
287 && self.c1 >= -EPSILON
288 && self.c2 <= EPSILON
289 && self.c2 >= -EPSILON
290 && self.c4 <= EPSILON
291 && self.c4 >= -EPSILON
292 && self.d1 <= EPSILON
293 && self.d1 >= -EPSILON
294 && self.d2 <= EPSILON
295 && self.d2 >= -EPSILON
296 && self.d3 <= EPSILON
297 && self.d3 >= -EPSILON
298 && self.a1 <= 1. + EPSILON
299 && self.a1 >= 1. - EPSILON
300 && self.b2 <= 1. + EPSILON
301 && self.b2 >= 1. - EPSILON
302 && self.c3 <= 1. + EPSILON
303 && self.c3 >= 1. - EPSILON
304 && self.d4 <= 1. + EPSILON
305 && self.d4 >= 1. - EPSILON
306 }
307}
308impl Default for Matrix4x4 {
309 fn default() -> Self {
310 Self::new(
311 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.,
312 )
313 }
314}
315impl ops::MulAssign<Matrix4x4> for [f32; 4] {
316 fn mul_assign(&mut self, m: Matrix4x4) {
317 let [x, y, z, w] = *self;
318 self[0] = m.a1 * x + m.a2 * y + m.a3 * z + m.a4 * w;
319 self[1] = m.b1 * x + m.b2 * y + m.b3 * z + m.b4 * w;
320 self[2] = m.c1 * x + m.c2 * y + m.c3 * z + m.c4 * w;
321 self[3] = m.d1 * x + m.d2 * y + m.d3 * z + m.d4 * w;
322 }
323}
324impl ops::MulAssign<Matrix4x4> for [f32; 3] {
325 fn mul_assign(&mut self, m: Matrix4x4) {
326 let mut result = [self[0], self[1], self[2], 1.];
327 result *= m;
328 *self = [result[0], result[1], result[2]];
329 }
330}
331impl ops::MulAssign for Matrix4x4 {
332 fn mul_assign(&mut self, m: Self) {
333 let t = *self;
334 self.a1 = m.a1 * t.a1 + m.b1 * t.a2 + m.c1 * t.a3 + m.d1 * t.a4;
335 self.a2 = m.a2 * t.a1 + m.b2 * t.a2 + m.c2 * t.a3 + m.d2 * t.a4;
336 self.a3 = m.a3 * t.a1 + m.b3 * t.a2 + m.c3 * t.a3 + m.d3 * t.a4;
337 self.a4 = m.a4 * t.a1 + m.b4 * t.a2 + m.c4 * t.a3 + m.d4 * t.a4;
338 self.b1 = m.a1 * t.b1 + m.b1 * t.b2 + m.c1 * t.b3 + m.d1 * t.b4;
339 self.b2 = m.a2 * t.b1 + m.b2 * t.b2 + m.c2 * t.b3 + m.d2 * t.b4;
340 self.b3 = m.a3 * t.b1 + m.b3 * t.b2 + m.c3 * t.b3 + m.d3 * t.b4;
341 self.b4 = m.a4 * t.b1 + m.b4 * t.b2 + m.c4 * t.b3 + m.d4 * t.b4;
342 self.c1 = m.a1 * t.c1 + m.b1 * t.c2 + m.c1 * t.c3 + m.d1 * t.c4;
343 self.c2 = m.a2 * t.c1 + m.b2 * t.c2 + m.c2 * t.c3 + m.d2 * t.c4;
344 self.c3 = m.a3 * t.c1 + m.b3 * t.c2 + m.c3 * t.c3 + m.d3 * t.c4;
345 self.c4 = m.a4 * t.c1 + m.b4 * t.c2 + m.c4 * t.c3 + m.d4 * t.c4;
346 self.d1 = m.a1 * t.d1 + m.b1 * t.d2 + m.c1 * t.d3 + m.d1 * t.d4;
347 self.d2 = m.a2 * t.d1 + m.b2 * t.d2 + m.c2 * t.d3 + m.d2 * t.d4;
348 self.d3 = m.a3 * t.d1 + m.b3 * t.d2 + m.c3 * t.d3 + m.d3 * t.d4;
349 self.d4 = m.a4 * t.d1 + m.b4 * t.d2 + m.c4 * t.d3 + m.d4 * t.d4;
350 }
351}
352
353pub(super) struct InstanceGeometry<'a> {
359 pub(super) url: Uri<'a, Geometry<'a>>,
365
366 pub(super) materials: BTreeMap<&'a str, SemanticMappingTable<'a>>,
367}
368
369pub(super) struct SemanticMappingTable<'a> {
388 pub(super) target: Uri<'a, Material<'a>>,
390 pub(super) symbol: &'a str,
392 }
394
395pub(super) fn parse_scene<'a>(
452 _cx: &mut Context<'a>,
453 node: xml::Node<'a, '_>,
454) -> io::Result<Scene<'a>> {
455 debug_assert_eq!(node.tag_name().name(), "scene");
456 let mut instance_visual_scene = None;
457
458 for child in node.element_children() {
459 match child.tag_name().name() {
460 "instance_visual_scene" => {
461 instance_visual_scene = Some(parse_instance_visual_scene(child)?);
462 }
463 "instance_physics_scene" | "instance_kinematics_scene" => {
464 }
471 "extra" => { }
472 _ => return Err(error::unexpected_child_elem(child)),
473 }
474 }
475
476 Ok(Scene {
477 instance_visual_scene,
478 })
479}
480
481fn parse_instance_visual_scene<'a>(node: xml::Node<'a, '_>) -> io::Result<InstanceVisualScene<'a>> {
482 debug_assert_eq!(node.tag_name().name(), "instance_visual_scene");
483 let url = node.parse_url("url")?;
484 Ok(InstanceVisualScene {
485 url,
488 })
489}
490
491pub(super) fn parse_library_visual_scenes<'a>(
492 cx: &mut Context<'a>,
493 node: xml::Node<'a, '_>,
494) -> io::Result<()> {
495 debug_assert_eq!(node.tag_name().name(), "library_visual_scenes");
496 for child in node.element_children() {
500 match child.tag_name().name() {
501 "visual_scene" => {
502 parse_visual_scene(child, &mut cx.library_visual_scenes.nodes)?;
503 }
504 "asset" | "extra" => { }
505 _ => return Err(error::unexpected_child_elem(child)),
506 }
507 }
508
509 Ok(())
514}
515
516fn parse_visual_scene<'a>(node: xml::Node<'a, '_>, nodes: &mut Vec<Node<'a>>) -> io::Result<()> {
517 debug_assert_eq!(node.tag_name().name(), "visual_scene");
518 let id = node.attribute("id");
519 let mut scene_nodes = vec![];
520 let this = Node {
521 id,
522 ..Default::default()
524 };
525 let this_index = nodes.len();
526 nodes.push(this);
527
528 for child in node.element_children() {
529 match child.tag_name().name() {
530 "node" => {
531 scene_nodes.push(parse_node(child, nodes, this_index)?);
532 }
533 "evaluate_scene" => {
534 }
541 "asset" | "extra" => { }
542 _ => return Err(error::unexpected_child_elem(child)),
543 }
544 }
545
546 Ok(())
547}
548
549fn parse_node<'a>(
580 node: xml::Node<'a, '_>,
581 nodes: &mut Vec<Node<'a>>,
582 parent: usize,
583) -> io::Result<usize> {
584 debug_assert_eq!(node.tag_name().name(), "node");
585 let _ty: NodeType = node.parse_attribute("type")?.unwrap_or_default();
586 let this = Node {
587 parent: Some(parent),
592 ..Default::default()
593 };
594 let this_index = nodes.len();
595 nodes.push(this);
596 let mut transforms = vec![];
597
598 for child in node.element_children() {
599 match child.tag_name().name() {
600 "node" => {
601 let _c = parse_node(child, nodes, this_index)?;
602 }
604
605 "lookat" => {
607 let content = xml::comma_to_period(child.trimmed_text());
608 let mut iter = xml::parse_float_array_exact(&content, 9);
609 let map_err = |e| {
611 format_err!(
612 "{e} in <{}> element ({})",
613 child.tag_name().name(),
614 child.text_location(),
615 )
616 };
617 let t = [
618 iter.next().unwrap().map_err(map_err)?,
619 iter.next().unwrap().map_err(map_err)?,
620 iter.next().unwrap().map_err(map_err)?,
621 iter.next().unwrap().map_err(map_err)?,
622 iter.next().unwrap().map_err(map_err)?,
623 iter.next().unwrap().map_err(map_err)?,
624 iter.next().unwrap().map_err(map_err)?,
625 iter.next().unwrap().map_err(map_err)?,
626 iter.next().unwrap().map_err(map_err)?,
627 ];
628 transforms.push(Transform::Lookat(t));
629 }
630 "matrix" => {
631 let content = xml::comma_to_period(child.trimmed_text());
632 let mut iter = xml::parse_float_array_exact(&content, 16);
633 let map_err = |e| {
635 format_err!(
636 "{e} in <{}> element ({})",
637 child.tag_name().name(),
638 child.text_location(),
639 )
640 };
641 let t = [
642 iter.next().unwrap().map_err(map_err)?,
643 iter.next().unwrap().map_err(map_err)?,
644 iter.next().unwrap().map_err(map_err)?,
645 iter.next().unwrap().map_err(map_err)?,
646 iter.next().unwrap().map_err(map_err)?,
647 iter.next().unwrap().map_err(map_err)?,
648 iter.next().unwrap().map_err(map_err)?,
649 iter.next().unwrap().map_err(map_err)?,
650 iter.next().unwrap().map_err(map_err)?,
651 iter.next().unwrap().map_err(map_err)?,
652 iter.next().unwrap().map_err(map_err)?,
653 iter.next().unwrap().map_err(map_err)?,
654 iter.next().unwrap().map_err(map_err)?,
655 iter.next().unwrap().map_err(map_err)?,
656 iter.next().unwrap().map_err(map_err)?,
657 iter.next().unwrap().map_err(map_err)?,
658 ];
659 transforms.push(Transform::Matrix(t));
660 }
661 "rotate" => {
662 let content = xml::comma_to_period(child.trimmed_text());
663 let mut iter = xml::parse_float_array_exact(&content, 4);
664 let map_err = |e| {
666 format_err!(
667 "{e} in <{}> element ({})",
668 child.tag_name().name(),
669 child.text_location(),
670 )
671 };
672 let t = [
673 iter.next().unwrap().map_err(map_err)?,
674 iter.next().unwrap().map_err(map_err)?,
675 iter.next().unwrap().map_err(map_err)?,
676 iter.next().unwrap().map_err(map_err)?,
677 ];
678 transforms.push(Transform::Rotate(t));
679 }
680 "scale" => {
681 let content = xml::comma_to_period(child.trimmed_text());
682 let mut iter = xml::parse_float_array_exact(&content, 3);
683 let map_err = |e| {
685 format_err!(
686 "{e} in <{}> element ({})",
687 child.tag_name().name(),
688 child.text_location(),
689 )
690 };
691 let t = [
692 iter.next().unwrap().map_err(map_err)?,
693 iter.next().unwrap().map_err(map_err)?,
694 iter.next().unwrap().map_err(map_err)?,
695 ];
696 transforms.push(Transform::Scale(t));
697 }
698 "skew" => {
699 let content = xml::comma_to_period(child.trimmed_text());
700 let mut iter = xml::parse_float_array_exact(&content, 7);
701 let map_err = |e| {
703 format_err!(
704 "{e} in <{}> element ({})",
705 child.tag_name().name(),
706 child.text_location(),
707 )
708 };
709 let t = [
710 iter.next().unwrap().map_err(map_err)?,
711 iter.next().unwrap().map_err(map_err)?,
712 iter.next().unwrap().map_err(map_err)?,
713 iter.next().unwrap().map_err(map_err)?,
714 iter.next().unwrap().map_err(map_err)?,
715 iter.next().unwrap().map_err(map_err)?,
716 iter.next().unwrap().map_err(map_err)?,
717 ];
718 transforms.push(Transform::Skew(t));
719 }
720 "translate" => {
721 let content = xml::comma_to_period(child.trimmed_text());
722 let mut iter = xml::parse_float_array_exact(&content, 3);
723 let map_err = |e| {
725 format_err!(
726 "{e} in <{}> element ({})",
727 child.tag_name().name(),
728 child.text_location(),
729 )
730 };
731 let t = [
732 iter.next().unwrap().map_err(map_err)?,
733 iter.next().unwrap().map_err(map_err)?,
734 iter.next().unwrap().map_err(map_err)?,
735 ];
736 transforms.push(Transform::Translate(t));
737 }
738
739 "instance_camera" => {}
741 "instance_controller" => {}
742 "instance_geometry" => {
743 nodes[this_index]
744 .instance_geometry
745 .push(parse_instance_geometry(child)?);
746 }
747 "instance_light" => {}
748 "instance_node" => {}
749
750 _ => {}
751 }
752 }
753
754 if !transforms.is_empty() {
755 nodes[this_index].transform = Transform::calculate_transform(&transforms);
756 }
757
758 Ok(this_index)
759}
760
761impl FromStr for NodeType {
762 type Err = io::Error;
763
764 fn from_str(s: &str) -> Result<Self, Self::Err> {
765 Ok(match s {
766 "NODE" => Self::Node,
767 "JOINT" => Self::Joint,
768 _ => bail!("unknown note type {:?}", s),
769 })
770 }
771}
772
773fn parse_instance_geometry<'a>(node: xml::Node<'a, '_>) -> io::Result<InstanceGeometry<'a>> {
774 debug_assert_eq!(node.tag_name().name(), "instance_geometry");
775 let url = node.parse_url("url")?;
776 let mut materials = BTreeMap::new();
777
778 for child in node.element_children() {
779 match child.tag_name().name() {
780 "bind_material" => {
781 parse_bind_material(child, &mut materials)?;
782 }
783 "extra" => { }
784 _ => return Err(error::unexpected_child_elem(child)),
785 }
786 }
787
788 Ok(InstanceGeometry {
789 url,
792 materials,
793 })
794}
795
796fn parse_bind_material<'a>(
809 node: xml::Node<'a, '_>,
810 materials: &mut BTreeMap<&'a str, SemanticMappingTable<'a>>,
811) -> io::Result<()> {
812 debug_assert_eq!(node.tag_name().name(), "bind_material");
813 for child in node.element_children() {
814 match child.tag_name().name() {
815 "technique_common" => {
816 for instance_mat_node in child.element_children() {
817 match instance_mat_node.tag_name().name() {
818 "instance_material" => {
819 let table = parse_instance_material(instance_mat_node)?;
820 materials.insert(table.symbol, table);
821 }
822 _ => return Err(error::unexpected_child_elem(instance_mat_node)),
823 }
824 }
825 }
826 "param" | "technique" | "extra" => { }
827 _ => return Err(error::unexpected_child_elem(child)),
828 }
829 }
831 Ok(())
832}
833
834fn parse_instance_material<'a>(node: xml::Node<'a, '_>) -> io::Result<SemanticMappingTable<'a>> {
849 debug_assert_eq!(node.tag_name().name(), "instance_material");
850 let target = node.parse_url("target")?;
851 let symbol = node.required_attribute("symbol")?;
852 for child in node.element_children() {
855 match child.tag_name().name() {
856 "bind_vertex_input" => {
857 let _semantic = child.required_attribute("semantic")?;
867 let _input_semantic: InputSemantic =
868 child.parse_required_attribute("input_semantic")?;
869 let _input_set: u32 = child.parse_attribute("input_set")?.unwrap_or(0);
870
871 }
879 "bind" => {
880 }
887 "extra" => { }
888 _ => return Err(error::unexpected_child_elem(child)),
889 }
890 }
891
892 Ok(SemanticMappingTable {
893 target,
894 symbol,
895 })
897}