1use alloc::sync::Arc;
2use bevy_derive::EnumVariantMeta;
3use bevy_ecs::resource::Resource;
4use bevy_math::Vec3;
5#[cfg(feature = "serialize")]
6use bevy_platform::collections::HashMap;
7use bevy_platform::collections::HashSet;
8use bytemuck::cast_slice;
9use core::hash::{Hash, Hasher};
10#[cfg(feature = "serialize")]
11use serde::{Deserialize, Serialize};
12use thiserror::Error;
13use wgpu_types::{BufferAddress, VertexAttribute, VertexFormat, VertexStepMode};
14
15#[derive(Debug, Clone, Copy, PartialEq)]
16pub struct MeshVertexAttribute {
17 pub name: &'static str,
19
20 pub id: MeshVertexAttributeId,
24
25 pub format: VertexFormat,
27}
28
29#[cfg(feature = "serialize")]
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub(crate) struct SerializedMeshVertexAttribute {
32 pub(crate) name: String,
33 pub(crate) id: MeshVertexAttributeId,
34 pub(crate) format: VertexFormat,
35}
36
37#[cfg(feature = "serialize")]
38impl SerializedMeshVertexAttribute {
39 pub(crate) fn from_mesh_vertex_attribute(attribute: MeshVertexAttribute) -> Self {
40 Self {
41 name: attribute.name.to_string(),
42 id: attribute.id,
43 format: attribute.format,
44 }
45 }
46
47 pub(crate) fn try_into_mesh_vertex_attribute(
48 self,
49 possible_attributes: &HashMap<Box<str>, MeshVertexAttribute>,
50 ) -> Option<MeshVertexAttribute> {
51 let attr = possible_attributes.get(self.name.as_str())?;
52 if attr.id == self.id {
53 Some(*attr)
54 } else {
55 None
56 }
57 }
58}
59
60impl MeshVertexAttribute {
61 pub const fn new(name: &'static str, id: u64, format: VertexFormat) -> Self {
62 Self {
63 name,
64 id: MeshVertexAttributeId(id),
65 format,
66 }
67 }
68
69 pub const fn at_shader_location(&self, shader_location: u32) -> VertexAttributeDescriptor {
70 VertexAttributeDescriptor::new(shader_location, self.id, self.name)
71 }
72}
73
74#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
75#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
76pub struct MeshVertexAttributeId(u64);
77
78impl From<MeshVertexAttribute> for MeshVertexAttributeId {
79 fn from(attribute: MeshVertexAttribute) -> Self {
80 attribute.id
81 }
82}
83
84#[derive(Debug, Clone, Hash, Eq, PartialEq)]
85pub struct MeshVertexBufferLayout {
86 pub(crate) attribute_ids: Vec<MeshVertexAttributeId>,
87 pub(crate) layout: VertexBufferLayout,
88}
89
90impl MeshVertexBufferLayout {
91 pub fn new(attribute_ids: Vec<MeshVertexAttributeId>, layout: VertexBufferLayout) -> Self {
92 Self {
93 attribute_ids,
94 layout,
95 }
96 }
97
98 #[inline]
99 pub fn contains(&self, attribute_id: impl Into<MeshVertexAttributeId>) -> bool {
100 self.attribute_ids.contains(&attribute_id.into())
101 }
102
103 #[inline]
104 pub fn attribute_ids(&self) -> &[MeshVertexAttributeId] {
105 &self.attribute_ids
106 }
107
108 #[inline]
109 pub fn layout(&self) -> &VertexBufferLayout {
110 &self.layout
111 }
112
113 pub fn get_layout(
114 &self,
115 attribute_descriptors: &[VertexAttributeDescriptor],
116 ) -> Result<VertexBufferLayout, MissingVertexAttributeError> {
117 let mut attributes = Vec::with_capacity(attribute_descriptors.len());
118 for attribute_descriptor in attribute_descriptors {
119 if let Some(index) = self
120 .attribute_ids
121 .iter()
122 .position(|id| *id == attribute_descriptor.id)
123 {
124 let layout_attribute = &self.layout.attributes[index];
125 attributes.push(VertexAttribute {
126 format: layout_attribute.format,
127 offset: layout_attribute.offset,
128 shader_location: attribute_descriptor.shader_location,
129 });
130 } else {
131 return Err(MissingVertexAttributeError {
132 id: attribute_descriptor.id,
133 name: attribute_descriptor.name,
134 pipeline_type: None,
135 });
136 }
137 }
138
139 Ok(VertexBufferLayout {
140 array_stride: self.layout.array_stride,
141 step_mode: self.layout.step_mode,
142 attributes,
143 })
144 }
145}
146
147#[derive(Error, Debug)]
148#[error("Mesh is missing requested attribute: {name} ({id:?}, pipeline type: {pipeline_type:?})")]
149pub struct MissingVertexAttributeError {
150 pub pipeline_type: Option<&'static str>,
151 id: MeshVertexAttributeId,
152 name: &'static str,
153}
154
155pub struct VertexAttributeDescriptor {
156 pub shader_location: u32,
157 pub id: MeshVertexAttributeId,
158 name: &'static str,
159}
160
161impl VertexAttributeDescriptor {
162 pub const fn new(shader_location: u32, id: MeshVertexAttributeId, name: &'static str) -> Self {
163 Self {
164 shader_location,
165 id,
166 name,
167 }
168 }
169}
170
171#[derive(Debug, Clone, PartialEq)]
172pub(crate) struct MeshAttributeData {
173 pub(crate) attribute: MeshVertexAttribute,
174 pub(crate) values: VertexAttributeValues,
175}
176
177#[cfg(feature = "serialize")]
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub(crate) struct SerializedMeshAttributeData {
180 pub(crate) attribute: SerializedMeshVertexAttribute,
181 pub(crate) values: VertexAttributeValues,
182}
183
184#[cfg(feature = "serialize")]
185impl SerializedMeshAttributeData {
186 pub(crate) fn from_mesh_attribute_data(data: MeshAttributeData) -> Self {
187 Self {
188 attribute: SerializedMeshVertexAttribute::from_mesh_vertex_attribute(data.attribute),
189 values: data.values,
190 }
191 }
192
193 pub(crate) fn try_into_mesh_attribute_data(
194 self,
195 possible_attributes: &HashMap<Box<str>, MeshVertexAttribute>,
196 ) -> Option<MeshAttributeData> {
197 let attribute = self
198 .attribute
199 .try_into_mesh_vertex_attribute(possible_attributes)?;
200 Some(MeshAttributeData {
201 attribute,
202 values: self.values,
203 })
204 }
205}
206
207#[inline]
222pub fn triangle_area_normal(a: [f32; 3], b: [f32; 3], c: [f32; 3]) -> [f32; 3] {
223 let (a, b, c) = (Vec3::from(a), Vec3::from(b), Vec3::from(c));
224 (b - a).cross(c - a).into()
225}
226
227#[inline]
229pub fn triangle_normal(a: [f32; 3], b: [f32; 3], c: [f32; 3]) -> [f32; 3] {
230 let (a, b, c) = (Vec3::from(a), Vec3::from(b), Vec3::from(c));
231 (b - a).cross(c - a).normalize_or_zero().into()
232}
233
234#[derive(Clone, Debug, EnumVariantMeta, PartialEq)]
237#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
238pub enum VertexAttributeValues {
239 Float32(Vec<f32>),
240 Sint32(Vec<i32>),
241 Uint32(Vec<u32>),
242 Float32x2(Vec<[f32; 2]>),
243 Sint32x2(Vec<[i32; 2]>),
244 Uint32x2(Vec<[u32; 2]>),
245 Float32x3(Vec<[f32; 3]>),
246 Sint32x3(Vec<[i32; 3]>),
247 Uint32x3(Vec<[u32; 3]>),
248 Float32x4(Vec<[f32; 4]>),
249 Sint32x4(Vec<[i32; 4]>),
250 Uint32x4(Vec<[u32; 4]>),
251 Sint16x2(Vec<[i16; 2]>),
252 Snorm16x2(Vec<[i16; 2]>),
253 Uint16x2(Vec<[u16; 2]>),
254 Unorm16x2(Vec<[u16; 2]>),
255 Sint16x4(Vec<[i16; 4]>),
256 Snorm16x4(Vec<[i16; 4]>),
257 Uint16x4(Vec<[u16; 4]>),
258 Unorm16x4(Vec<[u16; 4]>),
259 Sint8x2(Vec<[i8; 2]>),
260 Snorm8x2(Vec<[i8; 2]>),
261 Uint8x2(Vec<[u8; 2]>),
262 Unorm8x2(Vec<[u8; 2]>),
263 Sint8x4(Vec<[i8; 4]>),
264 Snorm8x4(Vec<[i8; 4]>),
265 Uint8x4(Vec<[u8; 4]>),
266 Unorm8x4(Vec<[u8; 4]>),
267}
268
269impl VertexAttributeValues {
270 #[expect(
273 clippy::match_same_arms,
274 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."
275 )]
276 pub fn len(&self) -> usize {
277 match self {
278 VertexAttributeValues::Float32(values) => values.len(),
279 VertexAttributeValues::Sint32(values) => values.len(),
280 VertexAttributeValues::Uint32(values) => values.len(),
281 VertexAttributeValues::Float32x2(values) => values.len(),
282 VertexAttributeValues::Sint32x2(values) => values.len(),
283 VertexAttributeValues::Uint32x2(values) => values.len(),
284 VertexAttributeValues::Float32x3(values) => values.len(),
285 VertexAttributeValues::Sint32x3(values) => values.len(),
286 VertexAttributeValues::Uint32x3(values) => values.len(),
287 VertexAttributeValues::Float32x4(values) => values.len(),
288 VertexAttributeValues::Sint32x4(values) => values.len(),
289 VertexAttributeValues::Uint32x4(values) => values.len(),
290 VertexAttributeValues::Sint16x2(values) => values.len(),
291 VertexAttributeValues::Snorm16x2(values) => values.len(),
292 VertexAttributeValues::Uint16x2(values) => values.len(),
293 VertexAttributeValues::Unorm16x2(values) => values.len(),
294 VertexAttributeValues::Sint16x4(values) => values.len(),
295 VertexAttributeValues::Snorm16x4(values) => values.len(),
296 VertexAttributeValues::Uint16x4(values) => values.len(),
297 VertexAttributeValues::Unorm16x4(values) => values.len(),
298 VertexAttributeValues::Sint8x2(values) => values.len(),
299 VertexAttributeValues::Snorm8x2(values) => values.len(),
300 VertexAttributeValues::Uint8x2(values) => values.len(),
301 VertexAttributeValues::Unorm8x2(values) => values.len(),
302 VertexAttributeValues::Sint8x4(values) => values.len(),
303 VertexAttributeValues::Snorm8x4(values) => values.len(),
304 VertexAttributeValues::Uint8x4(values) => values.len(),
305 VertexAttributeValues::Unorm8x4(values) => values.len(),
306 }
307 }
308
309 pub fn is_empty(&self) -> bool {
311 self.len() == 0
312 }
313
314 pub fn as_float3(&self) -> Option<&[[f32; 3]]> {
316 match self {
317 VertexAttributeValues::Float32x3(values) => Some(values),
318 _ => None,
319 }
320 }
321
322 #[expect(
326 clippy::match_same_arms,
327 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."
328 )]
329 pub fn get_bytes(&self) -> &[u8] {
330 match self {
331 VertexAttributeValues::Float32(values) => cast_slice(values),
332 VertexAttributeValues::Sint32(values) => cast_slice(values),
333 VertexAttributeValues::Uint32(values) => cast_slice(values),
334 VertexAttributeValues::Float32x2(values) => cast_slice(values),
335 VertexAttributeValues::Sint32x2(values) => cast_slice(values),
336 VertexAttributeValues::Uint32x2(values) => cast_slice(values),
337 VertexAttributeValues::Float32x3(values) => cast_slice(values),
338 VertexAttributeValues::Sint32x3(values) => cast_slice(values),
339 VertexAttributeValues::Uint32x3(values) => cast_slice(values),
340 VertexAttributeValues::Float32x4(values) => cast_slice(values),
341 VertexAttributeValues::Sint32x4(values) => cast_slice(values),
342 VertexAttributeValues::Uint32x4(values) => cast_slice(values),
343 VertexAttributeValues::Sint16x2(values) => cast_slice(values),
344 VertexAttributeValues::Snorm16x2(values) => cast_slice(values),
345 VertexAttributeValues::Uint16x2(values) => cast_slice(values),
346 VertexAttributeValues::Unorm16x2(values) => cast_slice(values),
347 VertexAttributeValues::Sint16x4(values) => cast_slice(values),
348 VertexAttributeValues::Snorm16x4(values) => cast_slice(values),
349 VertexAttributeValues::Uint16x4(values) => cast_slice(values),
350 VertexAttributeValues::Unorm16x4(values) => cast_slice(values),
351 VertexAttributeValues::Sint8x2(values) => cast_slice(values),
352 VertexAttributeValues::Snorm8x2(values) => cast_slice(values),
353 VertexAttributeValues::Uint8x2(values) => cast_slice(values),
354 VertexAttributeValues::Unorm8x2(values) => cast_slice(values),
355 VertexAttributeValues::Sint8x4(values) => cast_slice(values),
356 VertexAttributeValues::Snorm8x4(values) => cast_slice(values),
357 VertexAttributeValues::Uint8x4(values) => cast_slice(values),
358 VertexAttributeValues::Unorm8x4(values) => cast_slice(values),
359 }
360 }
361}
362
363impl From<&VertexAttributeValues> for VertexFormat {
364 fn from(values: &VertexAttributeValues) -> Self {
365 match values {
366 VertexAttributeValues::Float32(_) => VertexFormat::Float32,
367 VertexAttributeValues::Sint32(_) => VertexFormat::Sint32,
368 VertexAttributeValues::Uint32(_) => VertexFormat::Uint32,
369 VertexAttributeValues::Float32x2(_) => VertexFormat::Float32x2,
370 VertexAttributeValues::Sint32x2(_) => VertexFormat::Sint32x2,
371 VertexAttributeValues::Uint32x2(_) => VertexFormat::Uint32x2,
372 VertexAttributeValues::Float32x3(_) => VertexFormat::Float32x3,
373 VertexAttributeValues::Sint32x3(_) => VertexFormat::Sint32x3,
374 VertexAttributeValues::Uint32x3(_) => VertexFormat::Uint32x3,
375 VertexAttributeValues::Float32x4(_) => VertexFormat::Float32x4,
376 VertexAttributeValues::Sint32x4(_) => VertexFormat::Sint32x4,
377 VertexAttributeValues::Uint32x4(_) => VertexFormat::Uint32x4,
378 VertexAttributeValues::Sint16x2(_) => VertexFormat::Sint16x2,
379 VertexAttributeValues::Snorm16x2(_) => VertexFormat::Snorm16x2,
380 VertexAttributeValues::Uint16x2(_) => VertexFormat::Uint16x2,
381 VertexAttributeValues::Unorm16x2(_) => VertexFormat::Unorm16x2,
382 VertexAttributeValues::Sint16x4(_) => VertexFormat::Sint16x4,
383 VertexAttributeValues::Snorm16x4(_) => VertexFormat::Snorm16x4,
384 VertexAttributeValues::Uint16x4(_) => VertexFormat::Uint16x4,
385 VertexAttributeValues::Unorm16x4(_) => VertexFormat::Unorm16x4,
386 VertexAttributeValues::Sint8x2(_) => VertexFormat::Sint8x2,
387 VertexAttributeValues::Snorm8x2(_) => VertexFormat::Snorm8x2,
388 VertexAttributeValues::Uint8x2(_) => VertexFormat::Uint8x2,
389 VertexAttributeValues::Unorm8x2(_) => VertexFormat::Unorm8x2,
390 VertexAttributeValues::Sint8x4(_) => VertexFormat::Sint8x4,
391 VertexAttributeValues::Snorm8x4(_) => VertexFormat::Snorm8x4,
392 VertexAttributeValues::Uint8x4(_) => VertexFormat::Uint8x4,
393 VertexAttributeValues::Unorm8x4(_) => VertexFormat::Unorm8x4,
394 }
395 }
396}
397
398#[derive(Default, Clone, Debug, Hash, Eq, PartialEq)]
400pub struct VertexBufferLayout {
401 pub array_stride: BufferAddress,
403 pub step_mode: VertexStepMode,
405 pub attributes: Vec<VertexAttribute>,
407}
408
409impl VertexBufferLayout {
410 pub fn from_vertex_formats<T: IntoIterator<Item = VertexFormat>>(
415 step_mode: VertexStepMode,
416 vertex_formats: T,
417 ) -> Self {
418 let mut offset = 0;
419 let mut attributes = Vec::new();
420 for (shader_location, format) in vertex_formats.into_iter().enumerate() {
421 attributes.push(VertexAttribute {
422 format,
423 offset,
424 shader_location: shader_location as u32,
425 });
426 offset += format.size();
427 }
428
429 VertexBufferLayout {
430 array_stride: offset,
431 step_mode,
432 attributes,
433 }
434 }
435
436 pub fn offset_locations_by(mut self, location: u32) -> Self {
439 self.attributes.iter_mut().for_each(|attr| {
440 attr.shader_location += location;
441 });
442 self
443 }
444}
445
446#[derive(Clone, Debug)]
456pub struct MeshVertexBufferLayoutRef(pub Arc<MeshVertexBufferLayout>);
457
458#[derive(Clone, Default, Resource)]
460pub struct MeshVertexBufferLayouts(HashSet<Arc<MeshVertexBufferLayout>>);
461
462impl MeshVertexBufferLayouts {
463 pub fn insert(&mut self, layout: MeshVertexBufferLayout) -> MeshVertexBufferLayoutRef {
467 MeshVertexBufferLayoutRef(
472 self.0
473 .get_or_insert_with(&layout, |layout| Arc::new(layout.clone()))
474 .clone(),
475 )
476 }
477}
478
479impl PartialEq for MeshVertexBufferLayoutRef {
480 fn eq(&self, other: &Self) -> bool {
481 Arc::ptr_eq(&self.0, &other.0)
482 }
483}
484
485impl Eq for MeshVertexBufferLayoutRef {}
486
487impl Hash for MeshVertexBufferLayoutRef {
488 fn hash<H: Hasher>(&self, state: &mut H) {
489 (Arc::as_ptr(&self.0) as usize).hash(state);
492 }
493}