mod3d_base/
object.rs

1//a Imports
2use crate::hierarchy;
3use crate::Renderable;
4use crate::{
5    Component, Instantiable, Material, Mesh, ShortIndex, Skeleton, Texture, Transformation,
6    Vertices,
7};
8use hierarchy::Hierarchy;
9
10//a Object
11//tp Object
12/// A hierarchy of ObjectNode's
13///
14/// This can be flattened in to an Instantiable
15pub struct Object<'object, M, R>
16where
17    R: Renderable,
18    M: Material + 'object,
19{
20    /// Skeleton
21    pub skeleton: Option<Skeleton>,
22    /// All the vertices used
23    pub vertices: Vec<&'object Vertices<'object, R>>,
24    /// All the vertices used
25    pub textures: Vec<&'object Texture<'object, R>>,
26    /// All the materials used
27    pub materials: Vec<&'object M>,
28    /// The meshes etc that make up the object
29    pub components: Hierarchy<Component>,
30    // The roots of the bones and hierarchical recipes for traversal
31    // pub roots   : Vec<(usize, Recipe)>,
32    // Meshes - indices in to nodes.nodes array of the meshes in the order of instance
33    // pub meshes : Vec<usize>
34}
35
36//ip Display for Object
37impl<'object, M, R> std::fmt::Display for Object<'object, M, R>
38where
39    R: Renderable,
40    M: Material + 'object,
41{
42    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
43        writeln!(fmt, "Object: {{")?;
44        for v in &self.vertices {
45            writeln!(fmt, "  {v}")?;
46        }
47        writeln!(fmt, "}}")
48    }
49}
50
51//ip Default for Object
52impl<'object, M, R> Default for Object<'object, M, R>
53where
54    M: Material + 'object,
55    R: Renderable,
56{
57    fn default() -> Self {
58        Self::new()
59    }
60}
61
62//ip Object
63impl<'object, M, R> Object<'object, M, R>
64where
65    M: Material + 'object,
66    R: Renderable,
67{
68    //fp new
69    /// Create a new [Object] with no components
70    pub fn new() -> Self {
71        let skeleton = None;
72        let vertices = Vec::new();
73        let textures = Vec::new();
74        let materials = Vec::new();
75        let components = Hierarchy::new();
76        Self {
77            skeleton,
78            vertices,
79            textures,
80            materials,
81            components,
82        }
83    }
84
85    //ap vertices
86    /// Borrow one of the vertices
87    pub fn vertices(&self, n: ShortIndex) -> &Vertices<'object, R> {
88        self.vertices[n.as_usize()]
89    }
90
91    //ap texture
92    /// Borrow one of the textures
93    pub fn texture(&self, n: ShortIndex) -> &Texture<'object, R> {
94        self.textures[n.as_usize()]
95    }
96
97    //mp material
98    /// Borrow a materiaal from the object
99    pub fn material(&self, n: ShortIndex) -> &M {
100        self.materials[n.as_usize()]
101    }
102
103    //mp add_vertices
104    /// Add vertices to the object
105    pub fn add_vertices(&mut self, vertices: &'object Vertices<'object, R>) -> ShortIndex {
106        let n = self.vertices.len();
107        self.vertices.push(vertices);
108        n.into()
109    }
110
111    //mp add_texture
112    /// Add texture to the object
113    pub fn add_texture(&mut self, texture: &'object Texture<'object, R>) -> ShortIndex {
114        let n = self.textures.len();
115        self.textures.push(texture);
116        n.into()
117    }
118
119    //fp add_material
120    /// Add a material to the object
121    pub fn add_material(&mut self, material: &'object M) -> ShortIndex {
122        let n = self.materials.len();
123        self.materials.push(material);
124        n.into()
125    }
126
127    //fp add_component
128    /// Add a component to the hierarchy
129    pub fn add_component(
130        &mut self,
131        parent: Option<usize>,
132        transformation: Option<Transformation>,
133        mesh: Mesh,
134    ) -> usize {
135        let node = Component::new(transformation, mesh);
136        let child = self.components.add_node(node);
137        if let Some(parent) = parent {
138            self.components.relate(parent, child);
139        }
140        child
141    }
142
143    //fp relate
144    /// Add a relation between two components
145    pub fn relate(&mut self, parent: usize, child: usize) {
146        self.components.relate(parent, child);
147    }
148
149    //mp analyze
150    /// Analyze the object once it has been completely created
151    ///
152    /// This must be performed before clients are created, render
153    /// recipes are generated, or the object is deconnstructed into an
154    /// [Instantiable].
155    pub fn analyze(&mut self) {
156        self.components.find_roots();
157    }
158
159    //dp into_instantiable
160    /// Deconstruct the object into an [Instantiable] for the
161    /// renderable. This should be invoked after analysis and clients
162    /// have been created.
163    ///
164    /// This permits (for exampl in OpenGL) the CPU-side buffers in
165    /// the object to be dropped, but the GPU-side objects (created by
166    /// create_client) can be maintained. The [Instantiable] contains
167    /// only instances of the types for the [Renderable].
168    pub fn into_instantiable(self, renderer: &mut R) -> Instantiable<R> {
169        for v in &self.vertices {
170            v.create_client(renderer);
171        }
172        for t in &self.textures {
173            t.create_client(renderer);
174        }
175        let materials: Vec<R::Material> = self
176            .materials
177            .iter()
178            .map(|m| renderer.create_material_client(&self, m))
179            .collect();
180        Instantiable::<R>::new::<M>(
181            self.skeleton,
182            self.vertices,
183            self.textures,
184            materials,
185            self.components,
186        )
187    }
188
189    //zz All done
190}