1use alloc::sync::Arc;
2use bevy_derive::EnumVariantMeta;
3use bevy_ecs::resource::Resource;
4use bevy_math::Vec3;
5use bevy_platform::collections::HashSet;
6use bytemuck::cast_slice;
7use core::hash::{Hash, Hasher};
8use thiserror::Error;
9use wgpu_types::{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, Debug)]
112#[error("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
141#[inline]
156pub fn face_area_normal(a: [f32; 3], b: [f32; 3], c: [f32; 3]) -> [f32; 3] {
157 let (a, b, c) = (Vec3::from(a), Vec3::from(b), Vec3::from(c));
158 (b - a).cross(c - a).into()
159}
160
161#[inline]
163pub fn face_normal(a: [f32; 3], b: [f32; 3], c: [f32; 3]) -> [f32; 3] {
164 let (a, b, c) = (Vec3::from(a), Vec3::from(b), Vec3::from(c));
165 (b - a).cross(c - a).normalize().into()
166}
167
168#[derive(Clone, Debug, EnumVariantMeta)]
171pub enum VertexAttributeValues {
172 Float32(Vec<f32>),
173 Sint32(Vec<i32>),
174 Uint32(Vec<u32>),
175 Float32x2(Vec<[f32; 2]>),
176 Sint32x2(Vec<[i32; 2]>),
177 Uint32x2(Vec<[u32; 2]>),
178 Float32x3(Vec<[f32; 3]>),
179 Sint32x3(Vec<[i32; 3]>),
180 Uint32x3(Vec<[u32; 3]>),
181 Float32x4(Vec<[f32; 4]>),
182 Sint32x4(Vec<[i32; 4]>),
183 Uint32x4(Vec<[u32; 4]>),
184 Sint16x2(Vec<[i16; 2]>),
185 Snorm16x2(Vec<[i16; 2]>),
186 Uint16x2(Vec<[u16; 2]>),
187 Unorm16x2(Vec<[u16; 2]>),
188 Sint16x4(Vec<[i16; 4]>),
189 Snorm16x4(Vec<[i16; 4]>),
190 Uint16x4(Vec<[u16; 4]>),
191 Unorm16x4(Vec<[u16; 4]>),
192 Sint8x2(Vec<[i8; 2]>),
193 Snorm8x2(Vec<[i8; 2]>),
194 Uint8x2(Vec<[u8; 2]>),
195 Unorm8x2(Vec<[u8; 2]>),
196 Sint8x4(Vec<[i8; 4]>),
197 Snorm8x4(Vec<[i8; 4]>),
198 Uint8x4(Vec<[u8; 4]>),
199 Unorm8x4(Vec<[u8; 4]>),
200}
201
202impl VertexAttributeValues {
203 #[expect(
206 clippy::match_same_arms,
207 reason = "Although the `values` binding on some match arms may have matching types, each variant has different semantics; thus it's not guaranteed that they will use the same type forever."
208 )]
209 pub fn len(&self) -> usize {
210 match self {
211 VertexAttributeValues::Float32(values) => values.len(),
212 VertexAttributeValues::Sint32(values) => values.len(),
213 VertexAttributeValues::Uint32(values) => values.len(),
214 VertexAttributeValues::Float32x2(values) => values.len(),
215 VertexAttributeValues::Sint32x2(values) => values.len(),
216 VertexAttributeValues::Uint32x2(values) => values.len(),
217 VertexAttributeValues::Float32x3(values) => values.len(),
218 VertexAttributeValues::Sint32x3(values) => values.len(),
219 VertexAttributeValues::Uint32x3(values) => values.len(),
220 VertexAttributeValues::Float32x4(values) => values.len(),
221 VertexAttributeValues::Sint32x4(values) => values.len(),
222 VertexAttributeValues::Uint32x4(values) => values.len(),
223 VertexAttributeValues::Sint16x2(values) => values.len(),
224 VertexAttributeValues::Snorm16x2(values) => values.len(),
225 VertexAttributeValues::Uint16x2(values) => values.len(),
226 VertexAttributeValues::Unorm16x2(values) => values.len(),
227 VertexAttributeValues::Sint16x4(values) => values.len(),
228 VertexAttributeValues::Snorm16x4(values) => values.len(),
229 VertexAttributeValues::Uint16x4(values) => values.len(),
230 VertexAttributeValues::Unorm16x4(values) => values.len(),
231 VertexAttributeValues::Sint8x2(values) => values.len(),
232 VertexAttributeValues::Snorm8x2(values) => values.len(),
233 VertexAttributeValues::Uint8x2(values) => values.len(),
234 VertexAttributeValues::Unorm8x2(values) => values.len(),
235 VertexAttributeValues::Sint8x4(values) => values.len(),
236 VertexAttributeValues::Snorm8x4(values) => values.len(),
237 VertexAttributeValues::Uint8x4(values) => values.len(),
238 VertexAttributeValues::Unorm8x4(values) => values.len(),
239 }
240 }
241
242 pub fn is_empty(&self) -> bool {
244 self.len() == 0
245 }
246
247 pub fn as_float3(&self) -> Option<&[[f32; 3]]> {
249 match self {
250 VertexAttributeValues::Float32x3(values) => Some(values),
251 _ => None,
252 }
253 }
254
255 #[expect(
259 clippy::match_same_arms,
260 reason = "Although the `values` binding on some match arms may have matching types, each variant has different semantics; thus it's not guaranteed that they will use the same type forever."
261 )]
262 pub fn get_bytes(&self) -> &[u8] {
263 match self {
264 VertexAttributeValues::Float32(values) => cast_slice(values),
265 VertexAttributeValues::Sint32(values) => cast_slice(values),
266 VertexAttributeValues::Uint32(values) => cast_slice(values),
267 VertexAttributeValues::Float32x2(values) => cast_slice(values),
268 VertexAttributeValues::Sint32x2(values) => cast_slice(values),
269 VertexAttributeValues::Uint32x2(values) => cast_slice(values),
270 VertexAttributeValues::Float32x3(values) => cast_slice(values),
271 VertexAttributeValues::Sint32x3(values) => cast_slice(values),
272 VertexAttributeValues::Uint32x3(values) => cast_slice(values),
273 VertexAttributeValues::Float32x4(values) => cast_slice(values),
274 VertexAttributeValues::Sint32x4(values) => cast_slice(values),
275 VertexAttributeValues::Uint32x4(values) => cast_slice(values),
276 VertexAttributeValues::Sint16x2(values) => cast_slice(values),
277 VertexAttributeValues::Snorm16x2(values) => cast_slice(values),
278 VertexAttributeValues::Uint16x2(values) => cast_slice(values),
279 VertexAttributeValues::Unorm16x2(values) => cast_slice(values),
280 VertexAttributeValues::Sint16x4(values) => cast_slice(values),
281 VertexAttributeValues::Snorm16x4(values) => cast_slice(values),
282 VertexAttributeValues::Uint16x4(values) => cast_slice(values),
283 VertexAttributeValues::Unorm16x4(values) => cast_slice(values),
284 VertexAttributeValues::Sint8x2(values) => cast_slice(values),
285 VertexAttributeValues::Snorm8x2(values) => cast_slice(values),
286 VertexAttributeValues::Uint8x2(values) => cast_slice(values),
287 VertexAttributeValues::Unorm8x2(values) => cast_slice(values),
288 VertexAttributeValues::Sint8x4(values) => cast_slice(values),
289 VertexAttributeValues::Snorm8x4(values) => cast_slice(values),
290 VertexAttributeValues::Uint8x4(values) => cast_slice(values),
291 VertexAttributeValues::Unorm8x4(values) => cast_slice(values),
292 }
293 }
294}
295
296impl From<&VertexAttributeValues> for VertexFormat {
297 fn from(values: &VertexAttributeValues) -> Self {
298 match values {
299 VertexAttributeValues::Float32(_) => VertexFormat::Float32,
300 VertexAttributeValues::Sint32(_) => VertexFormat::Sint32,
301 VertexAttributeValues::Uint32(_) => VertexFormat::Uint32,
302 VertexAttributeValues::Float32x2(_) => VertexFormat::Float32x2,
303 VertexAttributeValues::Sint32x2(_) => VertexFormat::Sint32x2,
304 VertexAttributeValues::Uint32x2(_) => VertexFormat::Uint32x2,
305 VertexAttributeValues::Float32x3(_) => VertexFormat::Float32x3,
306 VertexAttributeValues::Sint32x3(_) => VertexFormat::Sint32x3,
307 VertexAttributeValues::Uint32x3(_) => VertexFormat::Uint32x3,
308 VertexAttributeValues::Float32x4(_) => VertexFormat::Float32x4,
309 VertexAttributeValues::Sint32x4(_) => VertexFormat::Sint32x4,
310 VertexAttributeValues::Uint32x4(_) => VertexFormat::Uint32x4,
311 VertexAttributeValues::Sint16x2(_) => VertexFormat::Sint16x2,
312 VertexAttributeValues::Snorm16x2(_) => VertexFormat::Snorm16x2,
313 VertexAttributeValues::Uint16x2(_) => VertexFormat::Uint16x2,
314 VertexAttributeValues::Unorm16x2(_) => VertexFormat::Unorm16x2,
315 VertexAttributeValues::Sint16x4(_) => VertexFormat::Sint16x4,
316 VertexAttributeValues::Snorm16x4(_) => VertexFormat::Snorm16x4,
317 VertexAttributeValues::Uint16x4(_) => VertexFormat::Uint16x4,
318 VertexAttributeValues::Unorm16x4(_) => VertexFormat::Unorm16x4,
319 VertexAttributeValues::Sint8x2(_) => VertexFormat::Sint8x2,
320 VertexAttributeValues::Snorm8x2(_) => VertexFormat::Snorm8x2,
321 VertexAttributeValues::Uint8x2(_) => VertexFormat::Uint8x2,
322 VertexAttributeValues::Unorm8x2(_) => VertexFormat::Unorm8x2,
323 VertexAttributeValues::Sint8x4(_) => VertexFormat::Sint8x4,
324 VertexAttributeValues::Snorm8x4(_) => VertexFormat::Snorm8x4,
325 VertexAttributeValues::Uint8x4(_) => VertexFormat::Uint8x4,
326 VertexAttributeValues::Unorm8x4(_) => VertexFormat::Unorm8x4,
327 }
328 }
329}
330
331#[derive(Default, Clone, Debug, Hash, Eq, PartialEq)]
333pub struct VertexBufferLayout {
334 pub array_stride: BufferAddress,
336 pub step_mode: VertexStepMode,
338 pub attributes: Vec<VertexAttribute>,
340}
341
342impl VertexBufferLayout {
343 pub fn from_vertex_formats<T: IntoIterator<Item = VertexFormat>>(
348 step_mode: VertexStepMode,
349 vertex_formats: T,
350 ) -> Self {
351 let mut offset = 0;
352 let mut attributes = Vec::new();
353 for (shader_location, format) in vertex_formats.into_iter().enumerate() {
354 attributes.push(VertexAttribute {
355 format,
356 offset,
357 shader_location: shader_location as u32,
358 });
359 offset += format.size();
360 }
361
362 VertexBufferLayout {
363 array_stride: offset,
364 step_mode,
365 attributes,
366 }
367 }
368
369 pub fn offset_locations_by(mut self, location: u32) -> Self {
372 self.attributes.iter_mut().for_each(|attr| {
373 attr.shader_location += location;
374 });
375 self
376 }
377}
378
379#[derive(Clone, Debug)]
389pub struct MeshVertexBufferLayoutRef(pub Arc<MeshVertexBufferLayout>);
390
391#[derive(Clone, Default, Resource)]
393pub struct MeshVertexBufferLayouts(HashSet<Arc<MeshVertexBufferLayout>>);
394
395impl MeshVertexBufferLayouts {
396 pub fn insert(&mut self, layout: MeshVertexBufferLayout) -> MeshVertexBufferLayoutRef {
400 MeshVertexBufferLayoutRef(
405 self.0
406 .get_or_insert_with(&layout, |layout| Arc::new(layout.clone()))
407 .clone(),
408 )
409 }
410}
411
412impl PartialEq for MeshVertexBufferLayoutRef {
413 fn eq(&self, other: &Self) -> bool {
414 Arc::ptr_eq(&self.0, &other.0)
415 }
416}
417
418impl Eq for MeshVertexBufferLayoutRef {}
419
420impl Hash for MeshVertexBufferLayoutRef {
421 fn hash<H: Hasher>(&self, state: &mut H) {
422 (Arc::as_ptr(&self.0) as usize).hash(state);
425 }
426}