|
| 1 | +//! `<asset>` library: meshes, hfields, textures, materials. |
| 2 | +
|
| 3 | +use crate::Pose; |
| 4 | + |
| 5 | +/// Container for all assets defined in a model (and its includes). |
| 6 | +#[derive(Default, Clone, Debug)] |
| 7 | +pub struct Assets { |
| 8 | + /// `<mesh>` definitions, keyed by name. |
| 9 | + pub meshes: Vec<Mesh>, |
| 10 | + /// `<hfield>` definitions, keyed by name. |
| 11 | + pub hfields: Vec<Hfield>, |
| 12 | + /// `<texture>` definitions (recorded only — not loaded). |
| 13 | + pub textures: Vec<Texture>, |
| 14 | + /// `<material>` definitions (recorded only). |
| 15 | + pub materials: Vec<Material>, |
| 16 | +} |
| 17 | + |
| 18 | +impl Assets { |
| 19 | + /// Looks up a `<mesh>` by name. |
| 20 | + pub fn mesh(&self, name: &str) -> Option<&Mesh> { |
| 21 | + self.meshes.iter().find(|m| m.name.as_deref() == Some(name)) |
| 22 | + } |
| 23 | + |
| 24 | + /// Looks up a `<hfield>` by name. |
| 25 | + pub fn hfield(&self, name: &str) -> Option<&Hfield> { |
| 26 | + self.hfields |
| 27 | + .iter() |
| 28 | + .find(|h| h.name.as_deref() == Some(name)) |
| 29 | + } |
| 30 | + |
| 31 | + /// Looks up a `<material>` by name. |
| 32 | + pub fn material(&self, name: &str) -> Option<&Material> { |
| 33 | + self.materials |
| 34 | + .iter() |
| 35 | + .find(|m| m.name.as_deref() == Some(name)) |
| 36 | + } |
| 37 | + |
| 38 | + /// Looks up a `<texture>` by name. |
| 39 | + pub fn texture(&self, name: &str) -> Option<&Texture> { |
| 40 | + self.textures |
| 41 | + .iter() |
| 42 | + .find(|t| t.name.as_deref() == Some(name)) |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +/// `<mesh>` asset. Either references a file or carries inline vertex/face data. |
| 47 | +#[derive(Default, Clone, Debug)] |
| 48 | +pub struct Mesh { |
| 49 | + /// Asset name. |
| 50 | + pub name: Option<String>, |
| 51 | + /// Class for default lookup. |
| 52 | + pub class: Option<String>, |
| 53 | + /// Mesh file path (relative to `meshdir` / model dir). |
| 54 | + pub file: Option<String>, |
| 55 | + /// Per-axis scale (default `[1, 1, 1]`). |
| 56 | + pub scale: [f64; 3], |
| 57 | + /// Reference pose applied to the source mesh before use. |
| 58 | + pub refpose: Pose, |
| 59 | + /// Inline vertex array (alternative to `file`). Flat `[x0, y0, z0, x1, …]`. |
| 60 | + pub inline_vertices: Option<Vec<f64>>, |
| 61 | + /// Inline normals. Optional even when `inline_vertices` is set. |
| 62 | + pub inline_normals: Option<Vec<f64>>, |
| 63 | + /// Inline triangle indices. |
| 64 | + pub inline_faces: Option<Vec<u32>>, |
| 65 | + /// `inertia` attribute: `"shell"`, `"convex"` (default), or `"exact"`. |
| 66 | + pub inertia: MeshInertia, |
| 67 | + /// Maximum number of vertices when computing the convex hull. |
| 68 | + pub max_hull_vert: Option<u32>, |
| 69 | + /// `smoothnormal` (visualisation only — recorded). |
| 70 | + pub smoothnormal: f64, |
| 71 | +} |
| 72 | + |
| 73 | +/// `<mesh inertia>` selector. |
| 74 | +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] |
| 75 | +pub enum MeshInertia { |
| 76 | + /// Surface integral. |
| 77 | + Shell, |
| 78 | + /// Convex-hull interior (default). |
| 79 | + #[default] |
| 80 | + Convex, |
| 81 | + /// Tetrahedral integration over all triangles. |
| 82 | + Exact, |
| 83 | + /// Treat as a point mass at the geometric centre. |
| 84 | + Legacy, |
| 85 | +} |
| 86 | + |
| 87 | +/// `<hfield>` heightfield asset. |
| 88 | +#[derive(Default, Clone, Debug)] |
| 89 | +pub struct Hfield { |
| 90 | + /// Asset name. |
| 91 | + pub name: Option<String>, |
| 92 | + /// Class. |
| 93 | + pub class: Option<String>, |
| 94 | + /// Number of grid rows. |
| 95 | + pub nrow: u32, |
| 96 | + /// Number of grid columns. |
| 97 | + pub ncol: u32, |
| 98 | + /// `(radius_x, radius_y, elevation_z, base_z)`. |
| 99 | + pub size: [f64; 4], |
| 100 | + /// File path (PNG / `.hfield`). |
| 101 | + pub file: Option<String>, |
| 102 | + /// Inline elevation data (`nrow * ncol` values, row-major). |
| 103 | + pub elevation: Option<Vec<f64>>, |
| 104 | +} |
| 105 | + |
| 106 | +/// `<texture>` asset (recorded only). |
| 107 | +#[derive(Default, Clone, Debug)] |
| 108 | +pub struct Texture { |
| 109 | + /// Asset name. |
| 110 | + pub name: Option<String>, |
| 111 | + /// Asset class. |
| 112 | + pub class: Option<String>, |
| 113 | + /// Texture type (`2d`, `cube`, `skybox`). |
| 114 | + pub type_: Option<String>, |
| 115 | + /// File path. |
| 116 | + pub file: Option<String>, |
| 117 | + /// `builtin` (`"none"`, `"gradient"`, `"checker"`, `"flat"`). |
| 118 | + pub builtin: Option<String>, |
| 119 | + /// Primary RGB. |
| 120 | + pub rgb1: Option<[f64; 3]>, |
| 121 | + /// Secondary RGB. |
| 122 | + pub rgb2: Option<[f64; 3]>, |
| 123 | +} |
| 124 | + |
| 125 | +/// `<material>` asset (recorded only). |
| 126 | +#[derive(Default, Clone, Debug)] |
| 127 | +pub struct Material { |
| 128 | + /// Asset name. |
| 129 | + pub name: Option<String>, |
| 130 | + /// Asset class. |
| 131 | + pub class: Option<String>, |
| 132 | + /// Texture reference. |
| 133 | + pub texture: Option<String>, |
| 134 | + /// `rgba`. |
| 135 | + pub rgba: Option<[f64; 4]>, |
| 136 | + /// `emission`. |
| 137 | + pub emission: f64, |
| 138 | + /// `specular`. |
| 139 | + pub specular: f64, |
| 140 | + /// `shininess`. |
| 141 | + pub shininess: f64, |
| 142 | + /// `roughness`. |
| 143 | + pub roughness: f64, |
| 144 | + /// `metallic`. |
| 145 | + pub metallic: f64, |
| 146 | +} |
0 commit comments