mod3d_base/
vertices.rs

1//a Imports
2use std::cell::{Ref, RefCell};
3
4use crate::{BufferDataAccessor, BufferIndexAccessor};
5use crate::{Renderable, VertexAttr};
6
7//a Vertices
8//tp Vertices
9/// A set of vertices using one or more [crate::BufferData] through [BufferAccessor]s.
10///
11/// A number of [Vertices] is used by an `Object`, its components and
12/// their meshes; one is used for each primitive within a mesh for its
13/// elements.  The actual elements will be sets of triangles (as
14/// stripes or whatever) which use these vertices.
15///
16/// A [Vertices] object includes a lot of options for vertices, and
17/// different renderers (or different render stages) may require
18/// different subsets of these indices. As such, in OpenGL for
19/// example, a [Vertices] object may end up with more than one
20/// `VAO`. This data is part of the [VerticesClient] struct associated
21/// with the [Vertices]. In WebGPU there may more than one render
22/// pipeline for different shader pipelines for the same set of
23/// vertices.
24///
25/// When it comes to creating an instance of a mesh, that instance
26/// will have specific transformations and materials for each of its
27/// primitives; rendering the instance with a shader will require
28/// enabling the [Vertices] client for that shader, setting
29/// appropriate render options (uniforms in OpenGL)
30///
31/// FIXME - change to using VertexDesc instead of VeretxAttr?
32///       - this requires removing VertexAttr from here and using that in its BufferDataAccessor
33#[derive(Debug)]
34pub struct Vertices<'vertices, R: Renderable> {
35    /// Indices related to primitives that use these vertices; if none
36    /// then a draw call is not indexed but uses a range of elements
37    indices: Option<&'vertices BufferIndexAccessor<'vertices, R>>,
38
39    /// Attributes of the vertices, which must include position, sorted by VertexAttr
40    attrs: Vec<&'vertices BufferDataAccessor<'vertices, R>>,
41
42    /// Client handle for this set of Vertices, updated when 'create_client' is invoked
43    rc_client: RefCell<R::Vertices>,
44}
45
46//ip Display for Vertices
47impl<'vertices, R: Renderable> std::fmt::Display for Vertices<'vertices, R>
48where
49    R: Renderable,
50{
51    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
52        writeln!(fmt, "Vertices:")?;
53        writeln!(fmt, "  indices: {:?}", self.indices)?;
54        for a in &self.attrs {
55            writeln!(fmt, "  {a:?}")?;
56        }
57        Ok(())
58    }
59}
60
61///ip Vertices
62impl<'vertices, R: Renderable> Vertices<'vertices, R> {
63    //fp new
64    /// Create a new [Vertices] object with no additional attributes
65    pub fn new(
66        indices: Option<&'vertices BufferIndexAccessor<'vertices, R>>,
67        position: &'vertices BufferDataAccessor<'vertices, R>,
68    ) -> Self {
69        let attrs = vec![position];
70        let rc_client = RefCell::new(R::Vertices::default());
71        Self {
72            indices,
73            attrs,
74            rc_client,
75        }
76    }
77
78    //mp add_attr
79    /// Add a [BufferAccessor] for a particular [VertexAttr]
80    ///
81    /// On creation the [Vertices] will have views for indices and
82    /// positions; this provides a means to add views for things such
83    /// as normal, tex coords, etc
84    pub fn add_attr(&mut self, accessor: &'vertices BufferDataAccessor<'vertices, R>) {
85        if let Some(p) = self
86            .attrs
87            .iter()
88            .position(|a| a.vertex_attr() == accessor.vertex_attr())
89        {
90            self.attrs[p] = accessor;
91        } else {
92            self.attrs.push(accessor);
93        }
94    }
95
96    //mp borrow_indices
97    /// Borrow the indices [BufferAccessor]
98    pub fn borrow_indices<'a>(&'a self) -> Option<&'a BufferIndexAccessor<'vertices, R>> {
99        self.indices
100    }
101
102    //mp borrow_attr
103    /// Borrow an attribute [BufferDataAccessor] if the [Vertices] has one
104    pub fn borrow_attr<'a>(
105        &'a self,
106        attr: VertexAttr,
107    ) -> Option<&'a BufferDataAccessor<'vertices, R>> {
108        self.attrs
109            .iter()
110            .position(|a| a.vertex_attr() == attr)
111            .map(|p| self.attrs[p])
112    }
113
114    //mp iter_attrs
115    /// Iterate through attributes
116    pub fn iter_attrs(&self) -> std::slice::Iter<&BufferDataAccessor<'vertices, R>> {
117        self.attrs.iter()
118    }
119
120    //mp create_client
121    /// Create the render buffer required by the BufferAccessor
122    pub fn create_client(&self, renderer: &mut R) {
123        if let Some(i) = self.indices {
124            i.create_client(renderer)
125        }
126        for data_accessor in self.iter_attrs() {
127            data_accessor.create_client(renderer);
128        }
129        *(self.rc_client.borrow_mut()) = renderer.create_vertices_client(self);
130    }
131
132    //ap borrow_client
133    /// Borrow the client
134    pub fn borrow_client(&self) -> Ref<R::Vertices> {
135        self.rc_client.borrow()
136    }
137
138    //zz All done
139}