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#[derive(Debug)]
33pub struct Vertices<'vertices, R: Renderable + ?Sized> {
34    /// Indices related to primitives that use these vertices; if none
35    /// then a draw call is not indexed but uses a range of elements
36    indices: Option<&'vertices BufferIndexAccessor<'vertices, R>>,
37    /// Attributes of the vertices, which must include position, sorted by VertexAttr
38    attrs: Vec<(VertexAttr, &'vertices BufferDataAccessor<'vertices, R>)>,
39    /// Client handle for this set of Vertices, updated when 'create_client' is invoked
40    rc_client: RefCell<R::Vertices>,
41}
42
43//ip Display for Vertices
44impl<'vertices, R: Renderable> std::fmt::Display for Vertices<'vertices, R>
45where
46    R: Renderable,
47{
48    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
49        writeln!(fmt, "Vertices:")?;
50        writeln!(fmt, "  indices: {:?}", self.indices)?;
51        for (n, a) in &self.attrs {
52            writeln!(fmt, "  {n:?}: {a:?}")?;
53        }
54        Ok(())
55    }
56}
57
58///ip Vertices
59impl<'vertices, R: Renderable> Vertices<'vertices, R> {
60    //fp new
61    /// Create a new [Vertices] object with no additional attributes
62    pub fn new(
63        indices: Option<&'vertices BufferIndexAccessor<'vertices, R>>,
64        position: &'vertices BufferDataAccessor<'vertices, R>,
65    ) -> Self {
66        let attrs = vec![(VertexAttr::Position, position)];
67        let rc_client = RefCell::new(R::Vertices::default());
68        Self {
69            indices,
70            attrs,
71            rc_client,
72        }
73    }
74
75    //mp add_attr
76    /// Add a [BufferAccessor] for a particular [VertexAttr]
77    ///
78    /// On creation the [Vertices] will have views for indices and
79    /// positions; this provides a means to add views for things such
80    /// as normal, tex coords, etc
81    pub fn add_attr(
82        &mut self,
83        attr: VertexAttr,
84        accessor: &'vertices BufferDataAccessor<'vertices, R>,
85    ) {
86        match self.attrs.binary_search_by(|(a, _)| a.cmp(&attr)) {
87            Ok(index) => {
88                self.attrs[index] = (attr, accessor);
89            }
90            Err(index) => {
91                self.attrs.insert(index, (attr, accessor));
92            }
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 [BufferAccessor] if the [Vertices] has one
104    pub fn borrow_attr<'a>(
105        &'a self,
106        attr: VertexAttr,
107    ) -> Option<&'a BufferDataAccessor<'vertices, R>> {
108        for i in 0..self.attrs.len() {
109            if self.attrs[i].0 == attr {
110                return Some(self.attrs[i].1);
111            }
112        }
113        None
114    }
115
116    //mp iter_attrs
117    /// Iterate through attributes
118    pub fn iter_attrs(&self) -> std::slice::Iter<(VertexAttr, &BufferDataAccessor<'vertices, R>)> {
119        self.attrs.iter()
120    }
121
122    //mp create_client
123    /// Create the render buffer required by the BufferAccessor
124    pub fn create_client(&self, renderer: &mut R) {
125        self.indices.map(|i| i.create_client(renderer));
126        for (attr, view) in self.iter_attrs() {
127            view.create_client(*attr, 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}