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}