1use alloc::sync::Arc;
2use bevy_derive::EnumVariantMeta;
3use bevy_ecs::system::Resource;
4use bevy_math::Vec3;
5use bevy_utils::HashSet;
6use bytemuck::cast_slice;
7use core::hash::{Hash, Hasher};
8use derive_more::derive::{Display, Error};
9use wgpu::{BufferAddress, VertexAttribute, VertexFormat, VertexStepMode};
10
11#[derive(Debug, Clone, Copy)]
12pub struct MeshVertexAttribute {
13 pub name: &'static str,
15
16 pub id: MeshVertexAttributeId,
20
21 pub format: VertexFormat,
23}
24
25impl MeshVertexAttribute {
26 pub const fn new(name: &'static str, id: u64, format: VertexFormat) -> Self {
27 Self {
28 name,
29 id: MeshVertexAttributeId(id),
30 format,
31 }
32 }
33
34 pub const fn at_shader_location(&self, shader_location: u32) -> VertexAttributeDescriptor {
35 VertexAttributeDescriptor::new(shader_location, self.id, self.name)
36 }
37}
38
39#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
40pub struct MeshVertexAttributeId(u64);
41
42impl From<MeshVertexAttribute> for MeshVertexAttributeId {
43 fn from(attribute: MeshVertexAttribute) -> Self {
44 attribute.id
45 }
46}
47
48#[derive(Debug, Clone, Hash, Eq, PartialEq)]
49pub struct MeshVertexBufferLayout {
50 pub(crate) attribute_ids: Vec<MeshVertexAttributeId>,
51 pub(crate) layout: VertexBufferLayout,
52}
53
54impl MeshVertexBufferLayout {
55 pub fn new(attribute_ids: Vec<MeshVertexAttributeId>, layout: VertexBufferLayout) -> Self {
56 Self {
57 attribute_ids,
58 layout,
59 }
60 }
61
62 #[inline]
63 pub fn contains(&self, attribute_id: impl Into<MeshVertexAttributeId>) -> bool {
64 self.attribute_ids.contains(&attribute_id.into())
65 }
66
67 #[inline]
68 pub fn attribute_ids(&self) -> &[MeshVertexAttributeId] {
69 &self.attribute_ids
70 }
71
72 #[inline]
73 pub fn layout(&self) -> &VertexBufferLayout {
74 &self.layout
75 }
76
77 pub fn get_layout(
78 &self,
79 attribute_descriptors: &[VertexAttributeDescriptor],
80 ) -> Result<VertexBufferLayout, MissingVertexAttributeError> {
81 let mut attributes = Vec::with_capacity(attribute_descriptors.len());
82 for attribute_descriptor in attribute_descriptors {
83 if let Some(index) = self
84 .attribute_ids
85 .iter()
86 .position(|id| *id == attribute_descriptor.id)
87 {
88 let layout_attribute = &self.layout.attributes[index];
89 attributes.push(VertexAttribute {
90 format: layout_attribute.format,
91 offset: layout_attribute.offset,
92 shader_location: attribute_descriptor.shader_location,
93 });
94 } else {
95 return Err(MissingVertexAttributeError {
96 id: attribute_descriptor.id,
97 name: attribute_descriptor.name,
98 pipeline_type: None,
99 });
100 }
101 }
102
103 Ok(VertexBufferLayout {
104 array_stride: self.layout.array_stride,
105 step_mode: self.layout.step_mode,
106 attributes,
107 })
108 }
109}
110
111#[derive(Error, Display, Debug)]
112#[display("Mesh is missing requested attribute: {name} ({id:?}, pipeline type: {pipeline_type:?})")]
113pub struct MissingVertexAttributeError {
114 pub pipeline_type: Option<&'static str>,
115 id: MeshVertexAttributeId,
116 name: &'static str,
117}
118
119pub struct VertexAttributeDescriptor {
120 pub shader_location: u32,
121 pub id: MeshVertexAttributeId,
122 name: &'static str,
123}
124
125impl VertexAttributeDescriptor {
126 pub const fn new(shader_location: u32, id: MeshVertexAttributeId, name: &'static str) -> Self {
127 Self {
128 shader_location,
129 id,
130 name,
131 }
132 }
133}
134
135#[derive(Debug, Clone)]
136pub(crate) struct MeshAttributeData {
137 pub(crate) attribute: MeshVertexAttribute,
138 pub(crate) values: VertexAttributeValues,
139}
140
141pub(crate) fn face_normal(a: [f32; 3], b: [f32; 3], c: [f32; 3]) -> [f32; 3] {
142 let (a, b, c) = (Vec3::from(a), Vec3::from(b), Vec3::from(c));
143 (b - a).cross(c - a).normalize().into()
144}
145
146pub trait VertexFormatSize {
147 fn get_size(self) -> u64;
148}
149
150impl VertexFormatSize for VertexFormat {
151 #[allow(clippy::match_same_arms)]
152 fn get_size(self) -> u64 {
153 match self {
154 VertexFormat::Uint8x2 => 2,
155 VertexFormat::Uint8x4 => 4,
156 VertexFormat::Sint8x2 => 2,
157 VertexFormat::Sint8x4 => 4,
158 VertexFormat::Unorm8x2 => 2,
159 VertexFormat::Unorm8x4 => 4,
160 VertexFormat::Snorm8x2 => 2,
161 VertexFormat::Snorm8x4 => 4,
162 VertexFormat::Unorm10_10_10_2 => 4,
163 VertexFormat::Uint16x2 => 2 * 2,
164 VertexFormat::Uint16x4 => 2 * 4,
165 VertexFormat::Sint16x2 => 2 * 2,
166 VertexFormat::Sint16x4 => 2 * 4,
167 VertexFormat::Unorm16x2 => 2 * 2,
168 VertexFormat::Unorm16x4 => 2 * 4,
169 VertexFormat::Snorm16x2 => 2 * 2,
170 VertexFormat::Snorm16x4 => 2 * 4,
171 VertexFormat::Float16x2 => 2 * 2,
172 VertexFormat::Float16x4 => 2 * 4,
173 VertexFormat::Float32 => 4,
174 VertexFormat::Float32x2 => 4 * 2,
175 VertexFormat::Float32x3 => 4 * 3,
176 VertexFormat::Float32x4 => 4 * 4,
177 VertexFormat::Uint32 => 4,
178 VertexFormat::Uint32x2 => 4 * 2,
179 VertexFormat::Uint32x3 => 4 * 3,
180 VertexFormat::Uint32x4 => 4 * 4,
181 VertexFormat::Sint32 => 4,
182 VertexFormat::Sint32x2 => 4 * 2,
183 VertexFormat::Sint32x3 => 4 * 3,
184 VertexFormat::Sint32x4 => 4 * 4,
185 VertexFormat::Float64 => 8,
186 VertexFormat::Float64x2 => 8 * 2,
187 VertexFormat::Float64x3 => 8 * 3,
188 VertexFormat::Float64x4 => 8 * 4,
189 }
190 }
191}
192
193#[derive(Clone, Debug, EnumVariantMeta)]
196pub enum VertexAttributeValues {
197 Float32(Vec<f32>),
198 Sint32(Vec<i32>),
199 Uint32(Vec<u32>),
200 Float32x2(Vec<[f32; 2]>),
201 Sint32x2(Vec<[i32; 2]>),
202 Uint32x2(Vec<[u32; 2]>),
203 Float32x3(Vec<[f32; 3]>),
204 Sint32x3(Vec<[i32; 3]>),
205 Uint32x3(Vec<[u32; 3]>),
206 Float32x4(Vec<[f32; 4]>),
207 Sint32x4(Vec<[i32; 4]>),
208 Uint32x4(Vec<[u32; 4]>),
209 Sint16x2(Vec<[i16; 2]>),
210 Snorm16x2(Vec<[i16; 2]>),
211 Uint16x2(Vec<[u16; 2]>),
212 Unorm16x2(Vec<[u16; 2]>),
213 Sint16x4(Vec<[i16; 4]>),
214 Snorm16x4(Vec<[i16; 4]>),
215 Uint16x4(Vec<[u16; 4]>),
216 Unorm16x4(Vec<[u16; 4]>),
217 Sint8x2(Vec<[i8; 2]>),
218 Snorm8x2(Vec<[i8; 2]>),
219 Uint8x2(Vec<[u8; 2]>),
220 Unorm8x2(Vec<[u8; 2]>),
221 Sint8x4(Vec<[i8; 4]>),
222 Snorm8x4(Vec<[i8; 4]>),
223 Uint8x4(Vec<[u8; 4]>),
224 Unorm8x4(Vec<[u8; 4]>),
225}
226
227impl VertexAttributeValues {
228 #[allow(clippy::match_same_arms)]
231 pub fn len(&self) -> usize {
232 match self {
233 VertexAttributeValues::Float32(values) => values.len(),
234 VertexAttributeValues::Sint32(values) => values.len(),
235 VertexAttributeValues::Uint32(values) => values.len(),
236 VertexAttributeValues::Float32x2(values) => values.len(),
237 VertexAttributeValues::Sint32x2(values) => values.len(),
238 VertexAttributeValues::Uint32x2(values) => values.len(),
239 VertexAttributeValues::Float32x3(values) => values.len(),
240 VertexAttributeValues::Sint32x3(values) => values.len(),
241 VertexAttributeValues::Uint32x3(values) => values.len(),
242 VertexAttributeValues::Float32x4(values) => values.len(),
243 VertexAttributeValues::Sint32x4(values) => values.len(),
244 VertexAttributeValues::Uint32x4(values) => values.len(),
245 VertexAttributeValues::Sint16x2(values) => values.len(),
246 VertexAttributeValues::Snorm16x2(values) => values.len(),
247 VertexAttributeValues::Uint16x2(values) => values.len(),
248 VertexAttributeValues::Unorm16x2(values) => values.len(),
249 VertexAttributeValues::Sint16x4(values) => values.len(),
250 VertexAttributeValues::Snorm16x4(values) => values.len(),
251 VertexAttributeValues::Uint16x4(values) => values.len(),
252 VertexAttributeValues::Unorm16x4(values) => values.len(),
253 VertexAttributeValues::Sint8x2(values) => values.len(),
254 VertexAttributeValues::Snorm8x2(values) => values.len(),
255 VertexAttributeValues::Uint8x2(values) => values.len(),
256 VertexAttributeValues::Unorm8x2(values) => values.len(),
257 VertexAttributeValues::Sint8x4(values) => values.len(),
258 VertexAttributeValues::Snorm8x4(values) => values.len(),
259 VertexAttributeValues::Uint8x4(values) => values.len(),
260 VertexAttributeValues::Unorm8x4(values) => values.len(),
261 }
262 }
263
264 pub fn is_empty(&self) -> bool {
266 self.len() == 0
267 }
268
269 pub fn as_float3(&self) -> Option<&[[f32; 3]]> {
271 match self {
272 VertexAttributeValues::Float32x3(values) => Some(values),
273 _ => None,
274 }
275 }
276
277 #[allow(clippy::match_same_arms)]
281 pub fn get_bytes(&self) -> &[u8] {
282 match self {
283 VertexAttributeValues::Float32(values) => cast_slice(values),
284 VertexAttributeValues::Sint32(values) => cast_slice(values),
285 VertexAttributeValues::Uint32(values) => cast_slice(values),
286 VertexAttributeValues::Float32x2(values) => cast_slice(values),
287 VertexAttributeValues::Sint32x2(values) => cast_slice(values),
288 VertexAttributeValues::Uint32x2(values) => cast_slice(values),
289 VertexAttributeValues::Float32x3(values) => cast_slice(values),
290 VertexAttributeValues::Sint32x3(values) => cast_slice(values),
291 VertexAttributeValues::Uint32x3(values) => cast_slice(values),
292 VertexAttributeValues::Float32x4(values) => cast_slice(values),
293 VertexAttributeValues::Sint32x4(values) => cast_slice(values),
294 VertexAttributeValues::Uint32x4(values) => cast_slice(values),
295 VertexAttributeValues::Sint16x2(values) => cast_slice(values),
296 VertexAttributeValues::Snorm16x2(values) => cast_slice(values),
297 VertexAttributeValues::Uint16x2(values) => cast_slice(values),
298 VertexAttributeValues::Unorm16x2(values) => cast_slice(values),
299 VertexAttributeValues::Sint16x4(values) => cast_slice(values),
300 VertexAttributeValues::Snorm16x4(values) => cast_slice(values),
301 VertexAttributeValues::Uint16x4(values) => cast_slice(values),
302 VertexAttributeValues::Unorm16x4(values) => cast_slice(values),
303 VertexAttributeValues::Sint8x2(values) => cast_slice(values),
304 VertexAttributeValues::Snorm8x2(values) => cast_slice(values),
305 VertexAttributeValues::Uint8x2(values) => cast_slice(values),
306 VertexAttributeValues::Unorm8x2(values) => cast_slice(values),
307 VertexAttributeValues::Sint8x4(values) => cast_slice(values),
308 VertexAttributeValues::Snorm8x4(values) => cast_slice(values),
309 VertexAttributeValues::Uint8x4(values) => cast_slice(values),
310 VertexAttributeValues::Unorm8x4(values) => cast_slice(values),
311 }
312 }
313}
314
315impl From<&VertexAttributeValues> for VertexFormat {
316 fn from(values: &VertexAttributeValues) -> Self {
317 match values {
318 VertexAttributeValues::Float32(_) => VertexFormat::Float32,
319 VertexAttributeValues::Sint32(_) => VertexFormat::Sint32,
320 VertexAttributeValues::Uint32(_) => VertexFormat::Uint32,
321 VertexAttributeValues::Float32x2(_) => VertexFormat::Float32x2,
322 VertexAttributeValues::Sint32x2(_) => VertexFormat::Sint32x2,
323 VertexAttributeValues::Uint32x2(_) => VertexFormat::Uint32x2,
324 VertexAttributeValues::Float32x3(_) => VertexFormat::Float32x3,
325 VertexAttributeValues::Sint32x3(_) => VertexFormat::Sint32x3,
326 VertexAttributeValues::Uint32x3(_) => VertexFormat::Uint32x3,
327 VertexAttributeValues::Float32x4(_) => VertexFormat::Float32x4,
328 VertexAttributeValues::Sint32x4(_) => VertexFormat::Sint32x4,
329 VertexAttributeValues::Uint32x4(_) => VertexFormat::Uint32x4,
330 VertexAttributeValues::Sint16x2(_) => VertexFormat::Sint16x2,
331 VertexAttributeValues::Snorm16x2(_) => VertexFormat::Snorm16x2,
332 VertexAttributeValues::Uint16x2(_) => VertexFormat::Uint16x2,
333 VertexAttributeValues::Unorm16x2(_) => VertexFormat::Unorm16x2,
334 VertexAttributeValues::Sint16x4(_) => VertexFormat::Sint16x4,
335 VertexAttributeValues::Snorm16x4(_) => VertexFormat::Snorm16x4,
336 VertexAttributeValues::Uint16x4(_) => VertexFormat::Uint16x4,
337 VertexAttributeValues::Unorm16x4(_) => VertexFormat::Unorm16x4,
338 VertexAttributeValues::Sint8x2(_) => VertexFormat::Sint8x2,
339 VertexAttributeValues::Snorm8x2(_) => VertexFormat::Snorm8x2,
340 VertexAttributeValues::Uint8x2(_) => VertexFormat::Uint8x2,
341 VertexAttributeValues::Unorm8x2(_) => VertexFormat::Unorm8x2,
342 VertexAttributeValues::Sint8x4(_) => VertexFormat::Sint8x4,
343 VertexAttributeValues::Snorm8x4(_) => VertexFormat::Snorm8x4,
344 VertexAttributeValues::Uint8x4(_) => VertexFormat::Uint8x4,
345 VertexAttributeValues::Unorm8x4(_) => VertexFormat::Unorm8x4,
346 }
347 }
348}
349
350#[derive(Default, Clone, Debug, Hash, Eq, PartialEq)]
352pub struct VertexBufferLayout {
353 pub array_stride: BufferAddress,
355 pub step_mode: VertexStepMode,
357 pub attributes: Vec<VertexAttribute>,
359}
360
361impl VertexBufferLayout {
362 pub fn from_vertex_formats<T: IntoIterator<Item = VertexFormat>>(
367 step_mode: VertexStepMode,
368 vertex_formats: T,
369 ) -> Self {
370 let mut offset = 0;
371 let mut attributes = Vec::new();
372 for (shader_location, format) in vertex_formats.into_iter().enumerate() {
373 attributes.push(VertexAttribute {
374 format,
375 offset,
376 shader_location: shader_location as u32,
377 });
378 offset += format.size();
379 }
380
381 VertexBufferLayout {
382 array_stride: offset,
383 step_mode,
384 attributes,
385 }
386 }
387
388 pub fn offset_locations_by(mut self, location: u32) -> Self {
391 self.attributes.iter_mut().for_each(|attr| {
392 attr.shader_location += location;
393 });
394 self
395 }
396}
397
398#[derive(Clone, Debug)]
408pub struct MeshVertexBufferLayoutRef(pub Arc<MeshVertexBufferLayout>);
409
410#[derive(Clone, Default, Resource)]
412pub struct MeshVertexBufferLayouts(HashSet<Arc<MeshVertexBufferLayout>>);
413
414impl MeshVertexBufferLayouts {
415 pub fn insert(&mut self, layout: MeshVertexBufferLayout) -> MeshVertexBufferLayoutRef {
419 MeshVertexBufferLayoutRef(
424 self.0
425 .get_or_insert_with(&layout, |layout| Arc::new(layout.clone()))
426 .clone(),
427 )
428 }
429}
430
431impl PartialEq for MeshVertexBufferLayoutRef {
432 fn eq(&self, other: &Self) -> bool {
433 Arc::ptr_eq(&self.0, &other.0)
434 }
435}
436
437impl Eq for MeshVertexBufferLayoutRef {}
438
439impl Hash for MeshVertexBufferLayoutRef {
440 fn hash<H: Hasher>(&self, state: &mut H) {
441 (Arc::as_ptr(&self.0) as usize).hash(state);
444 }
445}