1use crate::*;
2
3#[cfg(feature = "nalgebra")]
4use nalgebra::{Matrix4, Point3, Vector3};
5
6#[derive(Clone, Debug)]
9pub enum Transform {
10 LookAt(LookAt),
12 Matrix(Matrix),
14 Rotate(Rotate),
16 Scale(Scale),
18 Skew(Skew),
20 Translate(Translate),
22}
23
24impl From<LookAt> for Transform {
25 fn from(v: LookAt) -> Self {
26 Self::LookAt(v)
27 }
28}
29
30impl From<Matrix> for Transform {
31 fn from(v: Matrix) -> Self {
32 Self::Matrix(v)
33 }
34}
35
36impl From<Rotate> for Transform {
37 fn from(v: Rotate) -> Self {
38 Self::Rotate(v)
39 }
40}
41
42impl From<Scale> for Transform {
43 fn from(v: Scale) -> Self {
44 Self::Scale(v)
45 }
46}
47
48impl From<Skew> for Transform {
49 fn from(v: Skew) -> Self {
50 Self::Skew(v)
51 }
52}
53
54impl From<Translate> for Transform {
55 fn from(v: Translate) -> Self {
56 Self::Translate(v)
57 }
58}
59
60impl Transform {
61 pub fn parse(e: &Element) -> Result<Option<Self>> {
63 match e.name() {
64 LookAt::NAME => Ok(Some(Self::LookAt(LookAt::parse(e)?))),
65 Matrix::NAME => Ok(Some(Self::Matrix(Matrix::parse(e)?))),
66 Rotate::NAME => Ok(Some(Self::Rotate(Rotate::parse(e)?))),
67 Scale::NAME => Ok(Some(Self::Scale(Scale::parse(e)?))),
68 Skew::NAME => Ok(Some(Self::Skew(Skew::parse(e)?))),
69 Translate::NAME => Ok(Some(Self::Translate(Translate::parse(e)?))),
70 _ => Ok(None),
71 }
72 }
73
74 #[cfg(feature = "nalgebra")]
75 pub fn as_matrix(&self) -> Matrix4<f32> {
77 match self {
78 Transform::Translate(tr) => tr.as_matrix(),
79 Transform::Rotate(tr) => tr.as_matrix(),
80 Transform::LookAt(tr) => tr.as_matrix(),
81 Transform::Matrix(tr) => tr.as_matrix(),
82 Transform::Scale(tr) => tr.as_matrix(),
83 Transform::Skew(tr) => tr.as_matrix(),
84 }
85 }
86
87 #[cfg(feature = "nalgebra")]
88 pub fn prepend_to_matrix(&self, mat: &mut Matrix4<f32>) {
90 match self {
91 Transform::Translate(tr) => tr.prepend_to_matrix(mat),
92 Transform::Scale(tr) => tr.prepend_to_matrix(mat),
93 _ => *mat *= self.as_matrix(),
94 }
95 }
96
97 #[cfg(feature = "nalgebra")]
98 pub fn append_to_matrix(&self, mat: &mut Matrix4<f32>) {
100 match self {
101 Transform::Translate(tr) => tr.append_to_matrix(mat),
102 Transform::Scale(tr) => tr.append_to_matrix(mat),
103 _ => *mat = self.as_matrix() * *mat,
104 }
105 }
106}
107
108impl XNodeWrite for Transform {
109 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
110 match self {
111 Self::Translate(e) => e.write_to(w),
112 Self::Rotate(e) => e.write_to(w),
113 Self::LookAt(e) => e.write_to(w),
114 Self::Matrix(e) => e.write_to(w),
115 Self::Scale(e) => e.write_to(w),
116 Self::Skew(e) => e.write_to(w),
117 }
118 }
119}
120
121#[derive(Clone, Debug)]
124pub enum RigidTransform {
125 Translate(Translate),
127 Rotate(Rotate),
129}
130
131impl From<Translate> for RigidTransform {
132 fn from(v: Translate) -> Self {
133 Self::Translate(v)
134 }
135}
136
137impl From<Rotate> for RigidTransform {
138 fn from(v: Rotate) -> Self {
139 Self::Rotate(v)
140 }
141}
142
143impl From<RigidTransform> for Transform {
144 fn from(tr: RigidTransform) -> Self {
145 match tr {
146 RigidTransform::Translate(v) => v.into(),
147 RigidTransform::Rotate(v) => v.into(),
148 }
149 }
150}
151
152impl RigidTransform {
153 pub fn parse(e: &Element) -> Result<Option<Self>> {
155 match e.name() {
156 Translate::NAME => Ok(Some(Self::Translate(Translate::parse(e)?))),
157 Rotate::NAME => Ok(Some(Self::Rotate(Rotate::parse(e)?))),
158 _ => Ok(None),
159 }
160 }
161
162 #[cfg(feature = "nalgebra")]
163 pub fn as_matrix(&self) -> Matrix4<f32> {
165 match self {
166 RigidTransform::Translate(tr) => tr.as_matrix(),
167 RigidTransform::Rotate(tr) => tr.as_matrix(),
168 }
169 }
170
171 #[cfg(feature = "nalgebra")]
172 pub fn prepend_to_matrix(&self, mat: &mut Matrix4<f32>) {
174 match self {
175 RigidTransform::Translate(tr) => tr.prepend_to_matrix(mat),
176 _ => *mat *= self.as_matrix(),
177 }
178 }
179
180 #[cfg(feature = "nalgebra")]
181 pub fn append_to_matrix(&self, mat: &mut Matrix4<f32>) {
183 match self {
184 RigidTransform::Translate(tr) => tr.append_to_matrix(mat),
185 _ => *mat = self.as_matrix() * *mat,
186 }
187 }
188}
189
190impl XNodeWrite for RigidTransform {
191 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
192 match self {
193 Self::Translate(e) => e.write_to(w),
194 Self::Rotate(e) => e.write_to(w),
195 }
196 }
197}
198
199#[derive(Clone, Debug)]
201pub struct LookAt(
202 pub Box<[f32; 9]>,
208);
209
210impl XNode for LookAt {
211 const NAME: &'static str = "lookat";
212 fn parse(element: &Element) -> Result<Self> {
213 debug_assert_eq!(element.name(), Self::NAME);
214 Ok(LookAt(parse_array_n(element)?))
215 }
216}
217
218impl XNodeWrite for LookAt {
219 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
220 ElemBuilder::print_arr(Self::NAME, &*self.0, w)
221 }
222}
223
224impl LookAt {
225 pub fn new(eye: [f32; 3], target: [f32; 3], up: [f32; 3]) -> Self {
228 Self(Box::new([
229 eye[0], eye[1], eye[2], target[0], target[1], target[2], up[0], up[1], up[2],
230 ]))
231 }
232
233 #[inline]
235 pub fn eye(&self) -> &[f32; 3] {
236 self.0[0..3].try_into().unwrap()
237 }
238
239 #[inline]
241 pub fn target(&self) -> &[f32; 3] {
242 self.0[3..6].try_into().unwrap()
243 }
244
245 #[inline]
247 pub fn up(&self) -> &[f32; 3] {
248 self.0[6..9].try_into().unwrap()
249 }
250
251 #[cfg(feature = "nalgebra")]
252 pub fn as_matrix(&self) -> Matrix4<f32> {
254 let eye = Point3::from_slice(self.eye());
255 let target = Point3::from_slice(self.target());
256 let up = Vector3::from_column_slice(self.up());
257 Matrix4::look_at_rh(&eye, &target, &up)
258 }
259}
260
261#[derive(Clone, Debug)]
264pub struct Matrix(
265 pub Box<[f32; 16]>,
269);
270
271impl XNode for Matrix {
272 const NAME: &'static str = "matrix";
273 fn parse(element: &Element) -> Result<Self> {
274 debug_assert_eq!(element.name(), Self::NAME);
275 Ok(Matrix(parse_array_n(element)?))
276 }
277}
278
279impl XNodeWrite for Matrix {
280 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
281 ElemBuilder::print_arr(Self::NAME, &*self.0, w)
282 }
283}
284
285impl Matrix {
286 pub fn new(data: [f32; 16]) -> Self {
288 Self(Box::new(data))
289 }
290
291 #[cfg(feature = "nalgebra")]
292 pub fn as_matrix(&self) -> Matrix4<f32> {
294 Matrix4::from_row_slice(&*self.0)
297 }
298}
299
300#[cfg(feature = "nalgebra")]
301impl From<Matrix4<f32>> for Matrix {
302 fn from(mut mat: Matrix4<f32>) -> Self {
303 mat.transpose_mut();
306 Self(Box::new(mat.as_slice().try_into().expect("impossible")))
307 }
308}
309
310#[cfg(feature = "nalgebra")]
311impl From<Matrix4<f32>> for Transform {
312 fn from(mat: Matrix4<f32>) -> Self {
313 Self::Matrix(mat.into())
314 }
315}
316
317#[derive(Clone, Debug)]
319pub struct Rotate(
320 pub Box<[f32; 4]>,
324);
325
326impl XNode for Rotate {
327 const NAME: &'static str = "rotate";
328 fn parse(element: &Element) -> Result<Self> {
329 debug_assert_eq!(element.name(), Self::NAME);
330 Ok(Rotate(parse_array_n(element)?))
331 }
332}
333
334impl XNodeWrite for Rotate {
335 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
336 ElemBuilder::print_arr(Self::NAME, &*self.0, w)
337 }
338}
339
340impl Rotate {
341 pub fn new(axis: [f32; 3], angle: f32) -> Self {
343 Self(Box::new([axis[0], axis[1], axis[2], angle]))
344 }
345
346 pub fn axis(&self) -> &[f32; 3] {
348 self.0[0..3].try_into().unwrap()
349 }
350
351 pub fn angle(&self) -> f32 {
353 self.0[3]
354 }
355
356 #[cfg(feature = "nalgebra")]
357 pub fn as_matrix(&self) -> Matrix4<f32> {
359 let axis = Vector3::from_column_slice(self.axis()).normalize();
360 Matrix4::from_axis_angle(
361 &nalgebra::Unit::new_normalize(axis),
362 self.angle().to_radians(),
363 )
364 }
365}
366
367#[derive(Clone, Debug)]
369pub struct Scale(
370 pub Box<[f32; 3]>,
373);
374
375impl XNode for Scale {
376 const NAME: &'static str = "scale";
377 fn parse(element: &Element) -> Result<Self> {
378 debug_assert_eq!(element.name(), Self::NAME);
379 Ok(Scale(parse_array_n(element)?))
380 }
381}
382
383impl XNodeWrite for Scale {
384 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
385 ElemBuilder::print_arr(Self::NAME, &*self.0, w)
386 }
387}
388
389impl Scale {
390 pub fn new(val: [f32; 3]) -> Self {
392 Self(Box::new(val))
393 }
394
395 pub fn uniform(val: f32) -> Self {
397 Self::new([val, val, val])
398 }
399
400 #[cfg(feature = "nalgebra")]
401 pub fn as_matrix(&self) -> Matrix4<f32> {
403 Matrix4::new_nonuniform_scaling(&Vector3::from_row_slice(&*self.0))
404 }
405
406 #[cfg(feature = "nalgebra")]
407 pub fn prepend_to_matrix(&self, mat: &mut Matrix4<f32>) {
409 mat.prepend_nonuniform_scaling_mut(&Vector3::from_row_slice(&*self.0))
410 }
411
412 #[cfg(feature = "nalgebra")]
413 pub fn append_to_matrix(&self, mat: &mut Matrix4<f32>) {
415 mat.append_nonuniform_scaling_mut(&Vector3::from_row_slice(&*self.0))
416 }
417}
418
419#[derive(Clone, Debug)]
421pub struct Skew(
422 pub Box<[f32; 7]>,
426);
427
428impl XNode for Skew {
429 const NAME: &'static str = "skew";
430 fn parse(element: &Element) -> Result<Self> {
431 debug_assert_eq!(element.name(), Self::NAME);
432 Ok(Skew(parse_array_n(element)?))
433 }
434}
435
436impl XNodeWrite for Skew {
437 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
438 ElemBuilder::print_arr(Self::NAME, &*self.0, w)
439 }
440}
441
442impl Skew {
443 pub fn new(angle: f32, axis: [f32; 3], trans: [f32; 3]) -> Self {
445 Self(Box::new([
446 angle, axis[0], axis[1], axis[2], trans[0], trans[1], trans[2],
447 ]))
448 }
449
450 #[inline]
452 pub fn angle(&self) -> f32 {
453 self.0[0]
454 }
455
456 #[inline]
458 pub fn axis(&self) -> &[f32; 3] {
459 self.0[1..4].try_into().unwrap()
460 }
461
462 #[inline]
464 pub fn trans(&self) -> &[f32; 3] {
465 self.0[4..7].try_into().unwrap()
466 }
467
468 #[cfg(feature = "nalgebra")]
469 pub fn as_matrix(&self) -> Matrix4<f32> {
471 unimplemented!("<skew> transforms are not supported")
485 }
486}
487
488#[derive(Clone, Debug)]
490pub struct Translate(
491 pub Box<[f32; 3]>,
494);
495
496impl XNode for Translate {
497 const NAME: &'static str = "translate";
498 fn parse(element: &Element) -> Result<Self> {
499 debug_assert_eq!(element.name(), Self::NAME);
500 Ok(Translate(parse_array_n(element)?))
501 }
502}
503
504impl XNodeWrite for Translate {
505 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
506 ElemBuilder::print_arr(Self::NAME, &*self.0, w)
507 }
508}
509
510impl Translate {
511 pub fn new(val: [f32; 3]) -> Self {
513 Self(Box::new(val))
514 }
515
516 #[cfg(feature = "nalgebra")]
517 pub fn as_matrix(&self) -> Matrix4<f32> {
519 Matrix4::new_translation(&Vector3::from_row_slice(&*self.0))
520 }
521
522 #[cfg(feature = "nalgebra")]
523 pub fn prepend_to_matrix(&self, mat: &mut Matrix4<f32>) {
525 mat.prepend_translation_mut(&Vector3::from_row_slice(&*self.0))
526 }
527
528 #[cfg(feature = "nalgebra")]
529 pub fn append_to_matrix(&self, mat: &mut Matrix4<f32>) {
531 mat.append_translation_mut(&Vector3::from_row_slice(&*self.0))
532 }
533}