[go: up one dir, main page]

gltf/
lib.rs

1#![deny(missing_docs)]
2#![allow(unknown_lints)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5//! glTF 2.0 loader
6//!
7//! This crate is intended to load [glTF 2.0], a file format designed for the
8//! efficient runtime transmission of 3D scenes. The crate aims to provide
9//! rustic utilities that make working with glTF simple and intuitive.
10//!
11//! # Installation
12//!
13//! Add `gltf` to your `Cargo.toml`:
14//!
15//! ```toml
16//! [dependencies.gltf]
17//! version = "1"
18//! ```
19//!
20//! # Examples
21//!
22//! ## Basic usage
23//!
24//! Walking the node hierarchy.
25//!
26//! ```
27//! # fn run() -> Result<(), Box<dyn std::error::Error>> {
28//! # use gltf::Gltf;
29//! let gltf = Gltf::open("examples/Box.gltf")?;
30//! for scene in gltf.scenes() {
31//!     for node in scene.nodes() {
32//!         println!(
33//!             "Node #{} has {} children",
34//!             node.index(),
35//!             node.children().count(),
36//!         );
37//!     }
38//! }
39//! # Ok(())
40//! # }
41//! # fn main() {
42//! #    let _ = run().expect("runtime error");
43//! # }
44//! ```
45//!
46//! ## Import function
47//!
48//! Reading a glTF document plus its buffers and images from the
49//! file system.
50//!
51//! ```
52//! # fn run() -> Result<(), Box<dyn std::error::Error>> {
53//! let (document, buffers, images) = gltf::import("examples/Box.gltf")?;
54//! assert_eq!(buffers.len(), document.buffers().count());
55//! assert_eq!(images.len(), document.images().count());
56//! # Ok(())
57//! # }
58//! # fn main() {
59//! #    let _ = run().expect("runtime error");
60//! # }
61//! ```
62//!
63//! ### Note
64//!
65//! This function is provided as a convenience for loading glTF and associated
66//! resources from the file system. It is suitable for real world use but may
67//! not be suitable for all real world use cases. More complex import scenarios
68//! such downloading from web URLs are not handled by this function. These
69//! scenarios are delegated to the user.
70//!
71//! You can read glTF without loading resources by constructing the [`Gltf`]
72//! (standard glTF) or [`Glb`] (binary glTF) data structures explicitly. Buffer
73//! and image data can then be imported separately using [`import_buffers`] and
74//! [`import_images`] respectively.
75//!
76//! [glTF 2.0]: https://www.khronos.org/gltf
77//! [`Gltf`]: struct.Gltf.html
78//! [`Glb`]: struct.Glb.html
79//! [`Node`]: struct.Node.html
80//! [`Scene`]: struct.Scene.html
81
82#[cfg(test)]
83#[macro_use]
84extern crate approx;
85#[cfg(feature = "import")]
86extern crate image as image_crate;
87#[macro_use]
88extern crate lazy_static;
89
90/// Contains (de)serializable data structures that match the glTF JSON text.
91pub extern crate gltf_json as json;
92
93/// Accessors for reading vertex attributes from buffer views.
94pub mod accessor;
95
96/// Animations, their channels, targets, and samplers.
97pub mod animation;
98
99/// Primitives for working with binary glTF.
100pub mod binary;
101
102/// Buffers and buffer views.
103pub mod buffer;
104
105/// Cameras and their projections.
106pub mod camera;
107
108/// Images that may be used by textures.
109pub mod image;
110
111/// The reference importer.
112#[cfg(feature = "import")]
113#[cfg_attr(docsrs, doc(cfg(feature = "import")))]
114mod import;
115
116/// Iterators for walking the glTF node hierarchy.
117pub mod iter;
118
119/// Support for the `KHR_lights_punctual` extension.
120#[cfg(feature = "KHR_lights_punctual")]
121#[cfg_attr(docsrs, doc(cfg(feature = "KHR_lights_punctual")))]
122pub mod khr_lights_punctual;
123
124/// Support for the `KHR_materials_variants` extension.
125#[cfg(feature = "KHR_materials_variants")]
126#[cfg_attr(docsrs, doc(cfg(feature = "KHR_materials_variants")))]
127pub mod khr_materials_variants;
128
129/// Material properties of primitives.
130pub mod material;
131
132/// For internal use.
133mod math;
134
135/// Meshes and their primitives.
136pub mod mesh;
137
138/// The glTF node heirarchy.
139pub mod scene;
140
141/// Mesh skinning primitives.
142pub mod skin;
143
144/// Textures and their samplers.
145pub mod texture;
146
147#[cfg(feature = "extensions")]
148use json::Value;
149#[cfg(feature = "extensions")]
150use serde_json::Map;
151
152#[doc(inline)]
153pub use self::accessor::Accessor;
154#[doc(inline)]
155pub use self::animation::Animation;
156#[doc(inline)]
157pub use self::binary::Glb;
158#[doc(inline)]
159pub use self::buffer::Buffer;
160#[doc(inline)]
161pub use self::camera::Camera;
162#[doc(inline)]
163pub use self::image::Image;
164#[cfg(feature = "import")]
165#[doc(inline)]
166pub use self::import::import;
167#[cfg(feature = "import")]
168#[doc(inline)]
169pub use self::import::import_buffers;
170#[cfg(feature = "import")]
171#[doc(inline)]
172pub use self::import::import_images;
173#[cfg(feature = "import")]
174#[doc(inline)]
175pub use self::import::import_slice;
176#[doc(inline)]
177pub use self::material::Material;
178#[doc(inline)]
179pub use self::mesh::{Attribute, Mesh, Primitive, Semantic};
180#[doc(inline)]
181pub use self::scene::{Node, Scene};
182#[doc(inline)]
183pub use self::skin::Skin;
184#[doc(inline)]
185pub use self::texture::Texture;
186
187use std::path::Path;
188use std::{fs, io, ops, result};
189
190pub(crate) trait Normalize<T> {
191    fn normalize(self) -> T;
192}
193
194/// Result type for convenience.
195pub type Result<T> = result::Result<T, Error>;
196
197/// Represents a runtime error.
198#[derive(Debug)]
199pub enum Error {
200    /// Base 64 decoding error.
201    #[cfg(feature = "import")]
202    #[cfg_attr(docsrs, doc(cfg(feature = "import")))]
203    Base64(base64::DecodeError),
204
205    /// GLB parsing error.
206    Binary(binary::Error),
207
208    /// Buffer length does not match expected length.
209    #[cfg(feature = "import")]
210    #[cfg_attr(docsrs, doc(cfg(feature = "import")))]
211    BufferLength {
212        /// The index of the offending buffer.
213        buffer: usize,
214
215        /// The expected buffer length in bytes.
216        expected: usize,
217
218        /// The number of bytes actually available.
219        actual: usize,
220    },
221
222    /// JSON deserialization error.
223    Deserialize(json::Error),
224
225    /// Standard I/O error.
226    Io(std::io::Error),
227
228    /// Image decoding error.
229    #[cfg(feature = "import")]
230    #[cfg_attr(docsrs, doc(cfg(feature = "import")))]
231    Image(image_crate::ImageError),
232
233    /// The `BIN` chunk of binary glTF is referenced but does not exist.
234    #[cfg(feature = "import")]
235    #[cfg_attr(docsrs, doc(cfg(feature = "import")))]
236    MissingBlob,
237
238    /// An external file is referenced in a slice only import without path
239    #[cfg(feature = "import")]
240    #[cfg_attr(docsrs, doc(cfg(feature = "import")))]
241    ExternalReferenceInSliceImport,
242
243    /// Unsupported image encoding.
244    #[cfg(feature = "import")]
245    #[cfg_attr(docsrs, doc(cfg(feature = "import")))]
246    UnsupportedImageEncoding,
247
248    /// Unsupported image format.
249    #[cfg(feature = "import")]
250    #[cfg_attr(docsrs, doc(cfg(feature = "import")))]
251    UnsupportedImageFormat(image_crate::DynamicImage),
252
253    /// Unsupported URI scheme.
254    #[cfg(feature = "import")]
255    #[cfg_attr(docsrs, doc(cfg(feature = "import")))]
256    UnsupportedScheme,
257
258    /// glTF validation error.
259    Validation(Vec<(json::Path, json::validation::Error)>),
260}
261
262/// glTF JSON wrapper plus binary payload.
263#[derive(Clone, Debug)]
264pub struct Gltf {
265    /// The glTF JSON wrapper.
266    pub document: Document,
267
268    /// The glTF binary payload in the case of binary glTF.
269    pub blob: Option<Vec<u8>>,
270}
271
272/// glTF JSON wrapper.
273#[derive(Clone, Debug)]
274pub struct Document(json::Root);
275
276impl Gltf {
277    /// Convenience function that loads glTF from the file system.
278    pub fn open<P>(path: P) -> Result<Self>
279    where
280        P: AsRef<Path>,
281    {
282        let file = fs::File::open(path)?;
283        let reader = io::BufReader::new(file);
284        let gltf = Self::from_reader(reader)?;
285        Ok(gltf)
286    }
287
288    /// Loads glTF from a reader without performing validation checks.
289    pub fn from_reader_without_validation<R>(mut reader: R) -> Result<Self>
290    where
291        R: io::Read + io::Seek,
292    {
293        let mut magic = [0u8; 4];
294        reader.read_exact(&mut magic)?;
295        reader.seek(io::SeekFrom::Current(-4))?;
296        let (json, blob): (json::Root, Option<Vec<u8>>);
297        if magic.starts_with(b"glTF") {
298            let mut glb = binary::Glb::from_reader(reader)?;
299            // TODO: use `json::from_reader` instead of `json::from_slice`
300            json = json::deserialize::from_slice(&glb.json)?;
301            blob = glb.bin.take().map(|x| x.into_owned());
302        } else {
303            json = json::deserialize::from_reader(reader)?;
304            blob = None;
305        };
306        let document = Document::from_json_without_validation(json);
307        Ok(Gltf { document, blob })
308    }
309
310    /// Loads glTF from a reader.
311    pub fn from_reader<R>(reader: R) -> Result<Self>
312    where
313        R: io::Read + io::Seek,
314    {
315        let gltf = Self::from_reader_without_validation(reader)?;
316        gltf.document.validate()?;
317        Ok(gltf)
318    }
319
320    /// Loads glTF from a slice of bytes without performing validation
321    /// checks.
322    pub fn from_slice_without_validation(slice: &[u8]) -> Result<Self> {
323        let (json, blob): (json::Root, Option<Vec<u8>>);
324        if slice.starts_with(b"glTF") {
325            let mut glb = binary::Glb::from_slice(slice)?;
326            json = json::deserialize::from_slice(&glb.json)?;
327            blob = glb.bin.take().map(|x| x.into_owned());
328        } else {
329            json = json::deserialize::from_slice(slice)?;
330            blob = None;
331        };
332        let document = Document::from_json_without_validation(json);
333        Ok(Gltf { document, blob })
334    }
335
336    /// Loads glTF from a slice of bytes.
337    pub fn from_slice(slice: &[u8]) -> Result<Self> {
338        let gltf = Self::from_slice_without_validation(slice)?;
339        gltf.document.validate()?;
340        Ok(gltf)
341    }
342}
343
344impl ops::Deref for Gltf {
345    type Target = Document;
346    fn deref(&self) -> &Self::Target {
347        &self.document
348    }
349}
350
351impl ops::DerefMut for Gltf {
352    fn deref_mut(&mut self) -> &mut Self::Target {
353        &mut self.document
354    }
355}
356
357impl Document {
358    /// Loads glTF from pre-deserialized JSON.
359    pub fn from_json(json: json::Root) -> Result<Self> {
360        let document = Self::from_json_without_validation(json);
361        document.validate()?;
362        Ok(document)
363    }
364
365    /// Loads glTF from pre-deserialized JSON without performing
366    /// validation checks.
367    pub fn from_json_without_validation(json: json::Root) -> Self {
368        Document(json)
369    }
370
371    /// Unwraps the glTF document.
372    pub fn into_json(self) -> json::Root {
373        self.0
374    }
375
376    /// Unwraps the glTF document, without consuming it.
377    pub fn as_json(&self) -> &json::Root {
378        &self.0
379    }
380
381    /// Perform validation checks on loaded glTF.
382    pub(crate) fn validate(&self) -> Result<()> {
383        use json::validation::Validate;
384        let mut errors = Vec::new();
385        self.0
386            .validate(&self.0, json::Path::new, &mut |path, error| {
387                errors.push((path(), error))
388            });
389        if errors.is_empty() {
390            Ok(())
391        } else {
392            Err(Error::Validation(errors))
393        }
394    }
395
396    /// Returns an `Iterator` that visits the accessors of the glTF asset.
397    pub fn accessors(&self) -> iter::Accessors {
398        iter::Accessors {
399            iter: self.0.accessors.iter().enumerate(),
400            document: self,
401        }
402    }
403
404    /// Returns an `Iterator` that visits the animations of the glTF asset.
405    pub fn animations(&self) -> iter::Animations {
406        iter::Animations {
407            iter: self.0.animations.iter().enumerate(),
408            document: self,
409        }
410    }
411
412    /// Returns an `Iterator` that visits the pre-loaded buffers of the glTF asset.
413    pub fn buffers(&self) -> iter::Buffers {
414        iter::Buffers {
415            iter: self.0.buffers.iter().enumerate(),
416            document: self,
417        }
418    }
419
420    /// Returns an `Iterator` that visits the cameras of the glTF asset.
421    pub fn cameras(&self) -> iter::Cameras {
422        iter::Cameras {
423            iter: self.0.cameras.iter().enumerate(),
424            document: self,
425        }
426    }
427
428    /// Returns the default scene, if provided.
429    pub fn default_scene(&self) -> Option<Scene> {
430        self.0
431            .scene
432            .as_ref()
433            .map(|index| self.scenes().nth(index.value()).unwrap())
434    }
435
436    /// Returns the extensions referenced in this .document file.
437    pub fn extensions_used(&self) -> iter::ExtensionsUsed {
438        iter::ExtensionsUsed(self.0.extensions_used.iter())
439    }
440
441    /// Returns the extensions required to load and render this asset.
442    pub fn extensions_required(&self) -> iter::ExtensionsRequired {
443        iter::ExtensionsRequired(self.0.extensions_required.iter())
444    }
445
446    /// Returns an `Iterator` that visits the pre-loaded images of the glTF asset.
447    pub fn images(&self) -> iter::Images {
448        iter::Images {
449            iter: self.0.images.iter().enumerate(),
450            document: self,
451        }
452    }
453
454    /// Returns extension data unknown to this crate version.
455    #[cfg(feature = "extensions")]
456    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
457    pub fn extensions(&self) -> Option<&Map<String, Value>> {
458        let root = self.0.extensions.as_ref()?;
459        Some(&root.others)
460    }
461
462    /// Queries extension data unknown to this crate version.
463    #[cfg(feature = "extensions")]
464    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
465    pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
466        let root = self.0.extensions.as_ref()?;
467        root.others.get(ext_name)
468    }
469
470    /// Returns an `Iterator` that visits the lights of the glTF asset as defined by the
471    /// `KHR_lights_punctual` extension.
472    #[cfg(feature = "KHR_lights_punctual")]
473    #[cfg_attr(docsrs, doc(cfg(feature = "KHR_lights_punctual")))]
474    pub fn lights(&self) -> Option<iter::Lights> {
475        let iter = self
476            .0
477            .extensions
478            .as_ref()?
479            .khr_lights_punctual
480            .as_ref()?
481            .lights
482            .iter()
483            .enumerate();
484
485        Some(iter::Lights {
486            iter,
487            document: self,
488        })
489    }
490
491    /// Returns an `Iterator` that visits the variants of the glTF asset as defined by the
492    /// `KHR_materials_variants` extension.
493    #[cfg(feature = "KHR_materials_variants")]
494    #[cfg_attr(docsrs, doc(cfg(feature = "KHR_materials_variants")))]
495    pub fn variants(&self) -> Option<iter::Variants> {
496        let iter = self
497            .0
498            .extensions
499            .as_ref()?
500            .khr_materials_variants
501            .as_ref()?
502            .variants
503            .iter()
504            .enumerate();
505
506        Some(iter::Variants {
507            iter,
508            document: self,
509        })
510    }
511
512    /// Returns an `Iterator` that visits the materials of the glTF asset.
513    pub fn materials(&self) -> iter::Materials {
514        iter::Materials {
515            iter: self.0.materials.iter().enumerate(),
516            document: self,
517        }
518    }
519
520    /// Returns an `Iterator` that visits the meshes of the glTF asset.
521    pub fn meshes(&self) -> iter::Meshes {
522        iter::Meshes {
523            iter: self.0.meshes.iter().enumerate(),
524            document: self,
525        }
526    }
527
528    /// Returns an `Iterator` that visits the nodes of the glTF asset.
529    pub fn nodes(&self) -> iter::Nodes {
530        iter::Nodes {
531            iter: self.0.nodes.iter().enumerate(),
532            document: self,
533        }
534    }
535
536    /// Returns an `Iterator` that visits the samplers of the glTF asset.
537    pub fn samplers(&self) -> iter::Samplers {
538        iter::Samplers {
539            iter: self.0.samplers.iter().enumerate(),
540            document: self,
541        }
542    }
543
544    /// Returns an `Iterator` that visits the scenes of the glTF asset.
545    pub fn scenes(&self) -> iter::Scenes {
546        iter::Scenes {
547            iter: self.0.scenes.iter().enumerate(),
548            document: self,
549        }
550    }
551
552    /// Returns an `Iterator` that visits the skins of the glTF asset.
553    pub fn skins(&self) -> iter::Skins {
554        iter::Skins {
555            iter: self.0.skins.iter().enumerate(),
556            document: self,
557        }
558    }
559
560    /// Returns an `Iterator` that visits the textures of the glTF asset.
561    pub fn textures(&self) -> iter::Textures {
562        iter::Textures {
563            iter: self.0.textures.iter().enumerate(),
564            document: self,
565        }
566    }
567
568    /// Returns an `Iterator` that visits the pre-loaded buffer views of the glTF
569    /// asset.
570    pub fn views(&self) -> iter::Views {
571        iter::Views {
572            iter: self.0.buffer_views.iter().enumerate(),
573            document: self,
574        }
575    }
576}
577
578impl std::fmt::Display for Error {
579    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
580        match self {
581            #[cfg(feature = "import")]
582            Error::Base64(ref e) => e.fmt(f),
583            Error::Binary(ref e) => e.fmt(f),
584            #[cfg(feature = "import")]
585            Error::BufferLength {
586                buffer,
587                expected,
588                actual,
589            } => {
590                write!(
591                    f,
592                    "buffer {}: expected {} bytes but received {} bytes",
593                    buffer, expected, actual
594                )
595            }
596            Error::Deserialize(ref e) => e.fmt(f),
597            Error::Io(ref e) => e.fmt(f),
598            #[cfg(feature = "import")]
599            Error::Image(ref e) => e.fmt(f),
600            #[cfg(feature = "import")]
601            Error::MissingBlob => write!(f, "missing binary portion of binary glTF"),
602            #[cfg(feature = "import")]
603            Error::ExternalReferenceInSliceImport => {
604                write!(f, "external reference in slice only import")
605            }
606            #[cfg(feature = "import")]
607            Error::UnsupportedImageEncoding => write!(f, "unsupported image encoding"),
608            #[cfg(feature = "import")]
609            Error::UnsupportedImageFormat(image) => {
610                write!(f, "unsupported image format: {:?}", image.color())
611            }
612            #[cfg(feature = "import")]
613            Error::UnsupportedScheme => write!(f, "unsupported URI scheme"),
614            Error::Validation(ref xs) => {
615                write!(f, "invalid glTF:")?;
616                for (ref path, ref error) in xs {
617                    write!(f, " {}: {};", path, error)?;
618                }
619                Ok(())
620            }
621        }
622    }
623}
624
625impl std::error::Error for Error {}
626
627impl From<binary::Error> for Error {
628    fn from(err: binary::Error) -> Self {
629        Error::Binary(err)
630    }
631}
632
633impl From<std::io::Error> for Error {
634    fn from(err: std::io::Error) -> Self {
635        Error::Io(err)
636    }
637}
638
639#[cfg(feature = "import")]
640impl From<image_crate::ImageError> for Error {
641    fn from(err: image_crate::ImageError) -> Self {
642        Error::Image(err)
643    }
644}
645
646impl From<json::Error> for Error {
647    fn from(err: json::Error) -> Self {
648        Error::Deserialize(err)
649    }
650}
651
652impl From<Vec<(json::Path, json::validation::Error)>> for Error {
653    fn from(errs: Vec<(json::Path, json::validation::Error)>) -> Self {
654        Error::Validation(errs)
655    }
656}
657
658impl Normalize<i8> for i8 {
659    fn normalize(self) -> i8 {
660        self
661    }
662}
663
664impl Normalize<u8> for i8 {
665    fn normalize(self) -> u8 {
666        self.max(0) as u8 * 2
667    }
668}
669
670impl Normalize<i16> for i8 {
671    fn normalize(self) -> i16 {
672        self as i16 * 0x100
673    }
674}
675
676impl Normalize<u16> for i8 {
677    fn normalize(self) -> u16 {
678        self.max(0) as u16 * 0x200
679    }
680}
681
682impl Normalize<f32> for i8 {
683    fn normalize(self) -> f32 {
684        (self as f32 * 127.0_f32.recip()).max(-1.0)
685    }
686}
687
688impl Normalize<i8> for u8 {
689    fn normalize(self) -> i8 {
690        (self / 2) as i8
691    }
692}
693
694impl Normalize<u8> for u8 {
695    fn normalize(self) -> u8 {
696        self
697    }
698}
699
700impl Normalize<i16> for u8 {
701    fn normalize(self) -> i16 {
702        self as i16 * 0x80
703    }
704}
705
706impl Normalize<u16> for u8 {
707    fn normalize(self) -> u16 {
708        self as u16 * 0x100
709    }
710}
711
712impl Normalize<f32> for u8 {
713    fn normalize(self) -> f32 {
714        self as f32 * 255.0_f32.recip()
715    }
716}
717
718impl Normalize<i8> for i16 {
719    fn normalize(self) -> i8 {
720        (self / 0x100) as i8
721    }
722}
723
724impl Normalize<u8> for i16 {
725    fn normalize(self) -> u8 {
726        (self.max(0) / 0x80) as u8
727    }
728}
729
730impl Normalize<i16> for i16 {
731    fn normalize(self) -> i16 {
732        self
733    }
734}
735
736impl Normalize<u16> for i16 {
737    fn normalize(self) -> u16 {
738        self.max(0) as u16 * 2
739    }
740}
741
742impl Normalize<f32> for i16 {
743    fn normalize(self) -> f32 {
744        (self as f32 * 32767.0_f32.recip()).max(-1.0)
745    }
746}
747
748impl Normalize<i8> for u16 {
749    fn normalize(self) -> i8 {
750        (self / 0x200) as i8
751    }
752}
753
754impl Normalize<u8> for u16 {
755    fn normalize(self) -> u8 {
756        (self / 0x100) as u8
757    }
758}
759
760impl Normalize<i16> for u16 {
761    fn normalize(self) -> i16 {
762        (self / 2) as i16
763    }
764}
765
766impl Normalize<u16> for u16 {
767    fn normalize(self) -> u16 {
768        self
769    }
770}
771
772impl Normalize<f32> for u16 {
773    fn normalize(self) -> f32 {
774        self as f32 * 65535.0_f32.recip()
775    }
776}
777
778impl Normalize<i8> for f32 {
779    fn normalize(self) -> i8 {
780        (self * 127.0) as i8
781    }
782}
783
784impl Normalize<u8> for f32 {
785    fn normalize(self) -> u8 {
786        (self.max(0.0) * 255.0) as u8
787    }
788}
789
790impl Normalize<i16> for f32 {
791    fn normalize(self) -> i16 {
792        (self * 32767.0) as i16
793    }
794}
795
796impl Normalize<u16> for f32 {
797    fn normalize(self) -> u16 {
798        (self.max(0.0) * 65535.0) as u16
799    }
800}
801
802impl Normalize<f32> for f32 {
803    fn normalize(self) -> f32 {
804        self
805    }
806}
807
808impl<U, T> Normalize<[T; 2]> for [U; 2]
809where
810    U: Normalize<T> + Copy,
811{
812    fn normalize(self) -> [T; 2] {
813        [self[0].normalize(), self[1].normalize()]
814    }
815}
816
817impl<U, T> Normalize<[T; 3]> for [U; 3]
818where
819    U: Normalize<T> + Copy,
820{
821    fn normalize(self) -> [T; 3] {
822        [
823            self[0].normalize(),
824            self[1].normalize(),
825            self[2].normalize(),
826        ]
827    }
828}
829
830impl<U, T> Normalize<[T; 4]> for [U; 4]
831where
832    U: Normalize<T> + Copy,
833{
834    fn normalize(self) -> [T; 4] {
835        [
836            self[0].normalize(),
837            self[1].normalize(),
838            self[2].normalize(),
839            self[3].normalize(),
840        ]
841    }
842}