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}