1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
//! Vertex formats, associated types and functions. //! //! A vertex is a type representing a point. It’s common to find vertex positions, normals, colors //! or even texture coordinates. However, you’re free to use whichever type you want. Nevertheless, //! you’re limited to a range of types and dimensions. See `Type` and `Dim` for further details. //! //! # `Vertex` //! //! ## Rules //! //! To be able to use a type as a vertex, you have to implement the `Vertex` trait. That trait //! represents a mapping between your type and `VertexFormat`. A `VertexFormat` gives runtime hints //! about your type and restricts the supported type. If you cannot map your type to `VertexFormat`, //! that means you cannot use it as a `Vertex`. //! //! The rule is that your type should have a static size greater than 0 and less than or equal to 4. //! It should also be either integral, unsigned, floating or boolean. If your type is a complex one //! – for instance a `struct` – you have to recursively apply that rule to all its fields. //! For instance, the tuple `(i32, bool)` implements `Vertex` by providing an implementation using //! the ones of `i32` and `bool`. //! //! ## Components list //! //! As mentionned above, you can use tuples and structs as `Vertex`. If you look at the definition //! of `VertexFormat`, you’ll notice that it’s a `Vec<VertexComponentFormat>`. That means simple //! and primary types map to unit vectors – i.e. their size is 1 – but tuples and structs need //! several `VertexComponentFormat`s to be represented, hence vectors with sizes greater than 1. No //! check is made on how many vertex components you’re using – there’s a practical limit, set by the //! GPU, but it’s not checked (yet). //! //! # Generic implementation //! //! You have `Vertex` implementations for all the primary types that can be mapped to //! `VertexFormat`. However, as it’s not possible to automatically implement `Vertex` for your //! structure (yet?), a type is provided to help you design your vertex type so that you’re //! automatically provided with a `Vertex` implementation if you use `GTup`. //! //! `GTup` is a special type used to represent static heterogeneous list of types. With that in //! hand, you can easily create `Vertex` types and start using them without even implementing //! `Vertex`, as long as you use `Vertex` types. Feel free to dig in the `GTup` documentation for //! further details. //! //! If you absolutely want to use your own types – which is legit, you can implement `Vertex` by //! mapping your inner fields to a tuple or `GTup`, and call the right `Vertex` method on that //! tuple. use std::vec::Vec; use gtup::GTup; /// A `VertexFormat` is a list of `VertexComponentFormat`s. pub type VertexFormat = Vec<VertexComponentFormat>; /// Retrieve the number of components in a `VertexFormat`. pub fn vertex_format_size(vf: &[VertexComponentFormat]) -> usize { vf.len() } /// Vertex component format. It gives information on how vertices should be passed to the GPU and /// optimized in buffers. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct VertexComponentFormat { /// Type of the component. See `Type` for further details. pub comp_type: Type, /// Dimension of the component. It should be in 1–4. See `Dim` for further details. pub dim: Dim, /// Size in bytes that a single element of the component takes. That is, if your component has /// a dimension set to 2, then the unit size should be the size of a single element (not two). pub unit_size: usize, /// Alignment of the component. The best advice is to respect what Rust does, so it’s highly /// recommended to use `::std::mem::align_of` to let it does the job for you. pub align: usize } /// Possible type of vertex components. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Type { Integral, Unsigned, Floating, Boolean } /// Possible dimension of vertex components. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Dim { Dim1, Dim2, Dim3, Dim4 } /// A type that can be used as a `Vertex` has to implement that trait – it must provide a mapping /// to `VertexFormat`. /// /// If you’re not sure on how to implement that or if you want to use automatic types, feel free /// to use the primary supported types and `GTup` or tuples. pub trait Vertex { fn vertex_format() -> VertexFormat; } /// A hint trait to implement to state whether a vertex type is compatible with another. /// /// If you have two types `V0: Vertex` and `V1: Vertex`, we say that `V1` is compatible with `V0` /// only if `&V0::vertex_format()[0..V1::vertex_format().len()] == &V1::vertex_format()[..]`. That /// is, if `V1` is a sub-slice of `V0` starting at 0. /// /// We node that as `V1: CompatibleVertex<V0>`. pub trait CompatibleVertex<V>: Vertex where V: Vertex {} impl<V> CompatibleVertex<V> for V where V: Vertex {} /// Macro used to implement the `Vertex` trait. /// /// The first form implements `Vertex` for `$t`. `$q` refers to the inner representation of `$t` – /// for instance, `[f32; N]` has `f32` as inner representation. `$comp_type` is the type of the /// component (variant of `Type`) and `$dim` is the dimension (variant of `Dim`). /// /// The second form implement `Vertex` for `$t` for types that have the same inner representation /// than theirselves – usually, scalars. macro_rules! impl_base { ($t:ty, $q:ty, $comp_type:ident, $dim:ident) => { impl Vertex for $t { fn vertex_format() -> VertexFormat { vec![VertexComponentFormat { comp_type: Type::$comp_type, dim: Dim::$dim, unit_size: ::std::mem::size_of::<$q>(), align: ::std::mem::align_of::<$q>() }] } } }; ($t:ty, $comp_type:ident, $dim:ident) => { impl_base!($t, $t, $comp_type, $dim); } } macro_rules! impl_arr { ($t:ty, $q:ident) => { impl_base!([$t; 1], $t, $q, Dim1); impl_base!([$t; 2], $t, $q, Dim2); impl_base!([$t; 3], $t, $q, Dim3); impl_base!([$t; 4], $t, $q, Dim4); } } impl Vertex for () { fn vertex_format() -> VertexFormat { Vec::new() } } // scalars impl_base!(i8, Integral, Dim1); impl_base!(i16, Integral, Dim1); impl_base!(i32, Integral, Dim1); impl_base!(u8, Unsigned, Dim1); impl_base!(u16, Unsigned, Dim1); impl_base!(u32, Unsigned, Dim1); impl_base!(f32, Floating, Dim1); impl_base!(f64, Floating, Dim1); impl_base!(bool, Floating, Dim1); // arrays impl_arr!(i8, Integral); impl_arr!(i16, Integral); impl_arr!(i32, Integral); impl_arr!(u8, Unsigned); impl_arr!(u16, Unsigned); impl_arr!(u32, Unsigned); impl_arr!(f32, Floating); impl_arr!(f64, Floating); impl_arr!(bool, Boolean); impl<A, B> Vertex for GTup<A, B> where A: Vertex, B: Vertex { fn vertex_format() -> VertexFormat { let mut t = A::vertex_format(); t.extend(B::vertex_format()); t } } macro_rules! impl_vertex_for_tuple { ($($t:tt),+) => { impl<$($t),+> Vertex for ($($t),+) where $($t: Vertex),+ { fn vertex_format() -> VertexFormat { <gtup!(:$($t),+) as Vertex>::vertex_format() } } } } impl_vertex_for_tuple!(A, B); impl_vertex_for_tuple!(A, B, C); impl_vertex_for_tuple!(A, B, C, D); impl_vertex_for_tuple!(A, B, C, D, E); impl_vertex_for_tuple!(A, B, C, D, E, F); impl_vertex_for_tuple!(A, B, C, D, E, F, G); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);