Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_mesh/src/vertex.rs
9368 views
1
use alloc::sync::Arc;
2
use bevy_derive::EnumVariantMeta;
3
use bevy_ecs::resource::Resource;
4
use bevy_math::Vec3;
5
#[cfg(feature = "serialize")]
6
use bevy_platform::collections::HashMap;
7
use bevy_platform::collections::HashSet;
8
use bytemuck::{bytes_of, cast_slice};
9
use core::hash::{Hash, Hasher};
10
#[cfg(feature = "serialize")]
11
use serde::{Deserialize, Serialize};
12
use thiserror::Error;
13
use wgpu_types::{BufferAddress, VertexAttribute, VertexFormat, VertexStepMode};
14
15
#[derive(Debug, Clone, Copy, PartialEq)]
16
pub struct MeshVertexAttribute {
17
/// The friendly name of the vertex attribute
18
pub name: &'static str,
19
20
/// The _unique_ id of the vertex attribute. This will also determine sort ordering
21
/// when generating vertex buffers. Built-in / standard attributes will use "close to zero"
22
/// indices. When in doubt, use a random / very large u64 to avoid conflicts.
23
pub id: MeshVertexAttributeId,
24
25
/// The format of the vertex attribute.
26
pub format: VertexFormat,
27
}
28
29
#[cfg(feature = "serialize")]
30
#[derive(Debug, Clone, Serialize, Deserialize)]
31
pub(crate) struct SerializedMeshVertexAttribute {
32
pub(crate) name: String,
33
pub(crate) id: MeshVertexAttributeId,
34
pub(crate) format: VertexFormat,
35
}
36
37
#[cfg(feature = "serialize")]
38
impl 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
60
impl 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))]
76
pub struct MeshVertexAttributeId(u64);
77
78
impl From<MeshVertexAttribute> for MeshVertexAttributeId {
79
fn from(attribute: MeshVertexAttribute) -> Self {
80
attribute.id
81
}
82
}
83
84
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
85
pub struct MeshVertexBufferLayout {
86
pub(crate) attribute_ids: Vec<MeshVertexAttributeId>,
87
pub(crate) layout: VertexBufferLayout,
88
}
89
90
impl 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:?})")]
149
pub struct MissingVertexAttributeError {
150
pub pipeline_type: Option<&'static str>,
151
id: MeshVertexAttributeId,
152
name: &'static str,
153
}
154
155
pub struct VertexAttributeDescriptor {
156
pub shader_location: u32,
157
pub id: MeshVertexAttributeId,
158
name: &'static str,
159
}
160
161
impl 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)]
172
pub(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)]
179
pub(crate) struct SerializedMeshAttributeData {
180
pub(crate) attribute: SerializedMeshVertexAttribute,
181
pub(crate) values: VertexAttributeValues,
182
}
183
184
#[cfg(feature = "serialize")]
185
impl 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
/// Compute a vector whose direction is the normal of the triangle formed by
208
/// points a, b, c, and whose magnitude is double the area of the triangle. This
209
/// is useful for computing smooth normals where the contributing normals are
210
/// proportionate to the areas of the triangles as [discussed
211
/// here](https://iquilezles.org/articles/normals/).
212
///
213
/// Question: Why double the area? Because the area of a triangle _A_ is
214
/// determined by this equation:
215
///
216
/// _A = |(b - a) x (c - a)| / 2_
217
///
218
/// By computing _2 A_ we avoid a division operation, and when calculating the
219
/// the sum of these vectors which are then normalized, a constant multiple has
220
/// no effect.
221
#[inline]
222
pub 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
/// Compute the normal of a face made of three points: a, b, and c.
228
#[inline]
229
pub 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
/// Contains an array where each entry describes a property of a single vertex.
235
/// Matches the [`VertexFormats`](VertexFormat).
236
#[derive(Clone, Debug, EnumVariantMeta, PartialEq)]
237
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
238
pub 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
269
impl VertexAttributeValues {
270
/// Creates a new [`VertexAttributeValues`] with the storage for given [`VertexFormat`].
271
///
272
/// # Panics
273
///
274
/// Panics if the [`VertexFormat`] is not supported.
275
pub(crate) fn new(format: VertexFormat) -> Self {
276
match format {
277
VertexFormat::Uint8x2 => VertexAttributeValues::Uint8x2(Vec::new()),
278
VertexFormat::Uint8x4 => VertexAttributeValues::Uint8x4(Vec::new()),
279
VertexFormat::Sint8x2 => VertexAttributeValues::Sint8x2(Vec::new()),
280
VertexFormat::Sint8x4 => VertexAttributeValues::Sint8x4(Vec::new()),
281
VertexFormat::Unorm8x2 => VertexAttributeValues::Unorm8x2(Vec::new()),
282
VertexFormat::Unorm8x4 => VertexAttributeValues::Unorm8x4(Vec::new()),
283
VertexFormat::Snorm8x2 => VertexAttributeValues::Snorm8x2(Vec::new()),
284
VertexFormat::Snorm8x4 => VertexAttributeValues::Snorm8x4(Vec::new()),
285
VertexFormat::Uint16x2 => VertexAttributeValues::Uint16x2(Vec::new()),
286
VertexFormat::Uint16x4 => VertexAttributeValues::Uint16x4(Vec::new()),
287
VertexFormat::Sint16x2 => VertexAttributeValues::Sint16x2(Vec::new()),
288
VertexFormat::Sint16x4 => VertexAttributeValues::Sint16x4(Vec::new()),
289
VertexFormat::Unorm16x2 => VertexAttributeValues::Unorm16x2(Vec::new()),
290
VertexFormat::Unorm16x4 => VertexAttributeValues::Unorm16x4(Vec::new()),
291
VertexFormat::Snorm16x2 => VertexAttributeValues::Snorm16x2(Vec::new()),
292
VertexFormat::Snorm16x4 => VertexAttributeValues::Snorm16x4(Vec::new()),
293
VertexFormat::Float32 => VertexAttributeValues::Float32(Vec::new()),
294
VertexFormat::Float32x2 => VertexAttributeValues::Float32x2(Vec::new()),
295
VertexFormat::Float32x3 => VertexAttributeValues::Float32x3(Vec::new()),
296
VertexFormat::Float32x4 => VertexAttributeValues::Float32x4(Vec::new()),
297
VertexFormat::Uint32 => VertexAttributeValues::Uint32(Vec::new()),
298
VertexFormat::Uint32x2 => VertexAttributeValues::Uint32x2(Vec::new()),
299
VertexFormat::Uint32x3 => VertexAttributeValues::Uint32x3(Vec::new()),
300
VertexFormat::Uint32x4 => VertexAttributeValues::Uint32x4(Vec::new()),
301
VertexFormat::Sint32 => VertexAttributeValues::Sint32(Vec::new()),
302
VertexFormat::Sint32x2 => VertexAttributeValues::Sint32x2(Vec::new()),
303
VertexFormat::Sint32x3 => VertexAttributeValues::Sint32x3(Vec::new()),
304
VertexFormat::Sint32x4 => VertexAttributeValues::Sint32x4(Vec::new()),
305
VertexFormat::Uint8 => panic!("Uint8 is not supported"),
306
VertexFormat::Sint8 => panic!("Sint8 is not supported"),
307
VertexFormat::Snorm8 => panic!("Snorm8 is not supported"),
308
VertexFormat::Unorm8 => panic!("Unorm8 is not supported"),
309
VertexFormat::Uint16 => panic!("Uint16 is not supported"),
310
VertexFormat::Sint16 => panic!("Sint16 is not supported"),
311
VertexFormat::Snorm16 => panic!("Snorm16 is not supported"),
312
VertexFormat::Unorm16 => panic!("Unorm16 is not supported"),
313
VertexFormat::Float16 => panic!("Float16 is not supported"),
314
VertexFormat::Float16x2 => panic!("Float16x2 is not supported"),
315
VertexFormat::Float16x4 => panic!("Float16x4 is not supported"),
316
VertexFormat::Float64 => panic!("Float64 is not supported"),
317
VertexFormat::Float64x2 => panic!("Float64x2 is not supported"),
318
VertexFormat::Float64x3 => panic!("Float64x3 is not supported"),
319
VertexFormat::Float64x4 => panic!("Float64x4 is not supported"),
320
VertexFormat::Unorm8x4Bgra => panic!("Unorm8x4Bgra is not supported"),
321
VertexFormat::Unorm10_10_10_2 => panic!("Unorm10_10_10_2 is not supported"),
322
}
323
}
324
325
/// Returns the number of vertices in this [`VertexAttributeValues`]. For a single
326
/// mesh, all of the [`VertexAttributeValues`] must have the same length.
327
#[expect(
328
clippy::match_same_arms,
329
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."
330
)]
331
pub fn len(&self) -> usize {
332
match self {
333
VertexAttributeValues::Float32(values) => values.len(),
334
VertexAttributeValues::Sint32(values) => values.len(),
335
VertexAttributeValues::Uint32(values) => values.len(),
336
VertexAttributeValues::Float32x2(values) => values.len(),
337
VertexAttributeValues::Sint32x2(values) => values.len(),
338
VertexAttributeValues::Uint32x2(values) => values.len(),
339
VertexAttributeValues::Float32x3(values) => values.len(),
340
VertexAttributeValues::Sint32x3(values) => values.len(),
341
VertexAttributeValues::Uint32x3(values) => values.len(),
342
VertexAttributeValues::Float32x4(values) => values.len(),
343
VertexAttributeValues::Sint32x4(values) => values.len(),
344
VertexAttributeValues::Uint32x4(values) => values.len(),
345
VertexAttributeValues::Sint16x2(values) => values.len(),
346
VertexAttributeValues::Snorm16x2(values) => values.len(),
347
VertexAttributeValues::Uint16x2(values) => values.len(),
348
VertexAttributeValues::Unorm16x2(values) => values.len(),
349
VertexAttributeValues::Sint16x4(values) => values.len(),
350
VertexAttributeValues::Snorm16x4(values) => values.len(),
351
VertexAttributeValues::Uint16x4(values) => values.len(),
352
VertexAttributeValues::Unorm16x4(values) => values.len(),
353
VertexAttributeValues::Sint8x2(values) => values.len(),
354
VertexAttributeValues::Snorm8x2(values) => values.len(),
355
VertexAttributeValues::Uint8x2(values) => values.len(),
356
VertexAttributeValues::Unorm8x2(values) => values.len(),
357
VertexAttributeValues::Sint8x4(values) => values.len(),
358
VertexAttributeValues::Snorm8x4(values) => values.len(),
359
VertexAttributeValues::Uint8x4(values) => values.len(),
360
VertexAttributeValues::Unorm8x4(values) => values.len(),
361
}
362
}
363
364
/// Returns `true` if there are no vertices in this [`VertexAttributeValues`].
365
pub fn is_empty(&self) -> bool {
366
self.len() == 0
367
}
368
369
/// Returns the values as float triples if possible.
370
pub fn as_float3(&self) -> Option<&[[f32; 3]]> {
371
match self {
372
VertexAttributeValues::Float32x3(values) => Some(values),
373
_ => None,
374
}
375
}
376
377
// TODO: add vertex format as parameter here and perform type conversions
378
/// Flattens the [`VertexAttributeValues`] into a sequence of bytes. This is
379
/// useful for serialization and sending to the GPU.
380
#[expect(
381
clippy::match_same_arms,
382
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."
383
)]
384
pub fn get_bytes(&self) -> &[u8] {
385
match self {
386
VertexAttributeValues::Float32(values) => cast_slice(values),
387
VertexAttributeValues::Sint32(values) => cast_slice(values),
388
VertexAttributeValues::Uint32(values) => cast_slice(values),
389
VertexAttributeValues::Float32x2(values) => cast_slice(values),
390
VertexAttributeValues::Sint32x2(values) => cast_slice(values),
391
VertexAttributeValues::Uint32x2(values) => cast_slice(values),
392
VertexAttributeValues::Float32x3(values) => cast_slice(values),
393
VertexAttributeValues::Sint32x3(values) => cast_slice(values),
394
VertexAttributeValues::Uint32x3(values) => cast_slice(values),
395
VertexAttributeValues::Float32x4(values) => cast_slice(values),
396
VertexAttributeValues::Sint32x4(values) => cast_slice(values),
397
VertexAttributeValues::Uint32x4(values) => cast_slice(values),
398
VertexAttributeValues::Sint16x2(values) => cast_slice(values),
399
VertexAttributeValues::Snorm16x2(values) => cast_slice(values),
400
VertexAttributeValues::Uint16x2(values) => cast_slice(values),
401
VertexAttributeValues::Unorm16x2(values) => cast_slice(values),
402
VertexAttributeValues::Sint16x4(values) => cast_slice(values),
403
VertexAttributeValues::Snorm16x4(values) => cast_slice(values),
404
VertexAttributeValues::Uint16x4(values) => cast_slice(values),
405
VertexAttributeValues::Unorm16x4(values) => cast_slice(values),
406
VertexAttributeValues::Sint8x2(values) => cast_slice(values),
407
VertexAttributeValues::Snorm8x2(values) => cast_slice(values),
408
VertexAttributeValues::Uint8x2(values) => cast_slice(values),
409
VertexAttributeValues::Unorm8x2(values) => cast_slice(values),
410
VertexAttributeValues::Sint8x4(values) => cast_slice(values),
411
VertexAttributeValues::Snorm8x4(values) => cast_slice(values),
412
VertexAttributeValues::Uint8x4(values) => cast_slice(values),
413
VertexAttributeValues::Unorm8x4(values) => cast_slice(values),
414
}
415
}
416
417
#[expect(
418
clippy::match_same_arms,
419
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."
420
)]
421
pub(crate) fn get_bytes_at(&self, i: usize) -> &[u8] {
422
match self {
423
VertexAttributeValues::Float32(values) => bytes_of(&values[i]),
424
VertexAttributeValues::Sint32(values) => bytes_of(&values[i]),
425
VertexAttributeValues::Uint32(values) => bytes_of(&values[i]),
426
VertexAttributeValues::Float32x2(values) => bytes_of(&values[i]),
427
VertexAttributeValues::Sint32x2(values) => bytes_of(&values[i]),
428
VertexAttributeValues::Uint32x2(values) => bytes_of(&values[i]),
429
VertexAttributeValues::Float32x3(values) => bytes_of(&values[i]),
430
VertexAttributeValues::Sint32x3(values) => bytes_of(&values[i]),
431
VertexAttributeValues::Uint32x3(values) => bytes_of(&values[i]),
432
VertexAttributeValues::Float32x4(values) => bytes_of(&values[i]),
433
VertexAttributeValues::Sint32x4(values) => bytes_of(&values[i]),
434
VertexAttributeValues::Uint32x4(values) => bytes_of(&values[i]),
435
VertexAttributeValues::Sint16x2(values) => bytes_of(&values[i]),
436
VertexAttributeValues::Snorm16x2(values) => bytes_of(&values[i]),
437
VertexAttributeValues::Uint16x2(values) => bytes_of(&values[i]),
438
VertexAttributeValues::Unorm16x2(values) => bytes_of(&values[i]),
439
VertexAttributeValues::Sint16x4(values) => bytes_of(&values[i]),
440
VertexAttributeValues::Snorm16x4(values) => bytes_of(&values[i]),
441
VertexAttributeValues::Uint16x4(values) => bytes_of(&values[i]),
442
VertexAttributeValues::Unorm16x4(values) => bytes_of(&values[i]),
443
VertexAttributeValues::Sint8x2(values) => bytes_of(&values[i]),
444
VertexAttributeValues::Snorm8x2(values) => bytes_of(&values[i]),
445
VertexAttributeValues::Uint8x2(values) => bytes_of(&values[i]),
446
VertexAttributeValues::Unorm8x2(values) => bytes_of(&values[i]),
447
VertexAttributeValues::Sint8x4(values) => bytes_of(&values[i]),
448
VertexAttributeValues::Snorm8x4(values) => bytes_of(&values[i]),
449
VertexAttributeValues::Uint8x4(values) => bytes_of(&values[i]),
450
VertexAttributeValues::Unorm8x4(values) => bytes_of(&values[i]),
451
}
452
}
453
454
#[expect(
455
clippy::match_same_arms,
456
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."
457
)]
458
pub(crate) fn push_from(&mut self, source: &VertexAttributeValues, i: usize) {
459
match (self, source) {
460
(VertexAttributeValues::Float32(this), VertexAttributeValues::Float32(source)) => {
461
this.push(source[i]);
462
}
463
(VertexAttributeValues::Float32(_), _) => panic!("Mismatched vertex attribute values"),
464
(VertexAttributeValues::Sint32(this), VertexAttributeValues::Sint32(source)) => {
465
this.push(source[i]);
466
}
467
(VertexAttributeValues::Sint32(_), _) => panic!("Mismatched vertex attribute values"),
468
(VertexAttributeValues::Uint32(this), VertexAttributeValues::Uint32(source)) => {
469
this.push(source[i]);
470
}
471
(VertexAttributeValues::Uint32(_), _) => panic!("Mismatched vertex attribute values"),
472
(VertexAttributeValues::Float32x2(this), VertexAttributeValues::Float32x2(source)) => {
473
this.push(source[i]);
474
}
475
(VertexAttributeValues::Float32x2(_), _) => {
476
panic!("Mismatched vertex attribute values")
477
}
478
(VertexAttributeValues::Sint32x2(this), VertexAttributeValues::Sint32x2(source)) => {
479
this.push(source[i]);
480
}
481
(VertexAttributeValues::Sint32x2(_), _) => panic!("Mismatched vertex attribute values"),
482
(VertexAttributeValues::Uint32x2(this), VertexAttributeValues::Uint32x2(source)) => {
483
this.push(source[i]);
484
}
485
(VertexAttributeValues::Uint32x2(_), _) => panic!("Mismatched vertex attribute values"),
486
(VertexAttributeValues::Float32x3(this), VertexAttributeValues::Float32x3(source)) => {
487
this.push(source[i]);
488
}
489
(VertexAttributeValues::Float32x3(_), _) => {
490
panic!("Mismatched vertex attribute values")
491
}
492
(VertexAttributeValues::Sint32x3(this), VertexAttributeValues::Sint32x3(source)) => {
493
this.push(source[i]);
494
}
495
(VertexAttributeValues::Sint32x3(_), _) => panic!("Mismatched vertex attribute values"),
496
(VertexAttributeValues::Uint32x3(this), VertexAttributeValues::Uint32x3(source)) => {
497
this.push(source[i]);
498
}
499
(VertexAttributeValues::Uint32x3(_), _) => panic!("Mismatched vertex attribute values"),
500
(VertexAttributeValues::Float32x4(this), VertexAttributeValues::Float32x4(source)) => {
501
this.push(source[i]);
502
}
503
(VertexAttributeValues::Float32x4(_), _) => {
504
panic!("Mismatched vertex attribute values")
505
}
506
(VertexAttributeValues::Sint32x4(this), VertexAttributeValues::Sint32x4(source)) => {
507
this.push(source[i]);
508
}
509
(VertexAttributeValues::Sint32x4(_), _) => panic!("Mismatched vertex attribute values"),
510
(VertexAttributeValues::Uint32x4(this), VertexAttributeValues::Uint32x4(source)) => {
511
this.push(source[i]);
512
}
513
(VertexAttributeValues::Uint32x4(_), _) => panic!("Mismatched vertex attribute values"),
514
(VertexAttributeValues::Sint16x2(this), VertexAttributeValues::Sint16x2(source)) => {
515
this.push(source[i]);
516
}
517
(VertexAttributeValues::Sint16x2(_), _) => panic!("Mismatched vertex attribute values"),
518
(VertexAttributeValues::Snorm16x2(this), VertexAttributeValues::Snorm16x2(source)) => {
519
this.push(source[i]);
520
}
521
(VertexAttributeValues::Snorm16x2(_), _) => {
522
panic!("Mismatched vertex attribute values")
523
}
524
(VertexAttributeValues::Uint16x2(this), VertexAttributeValues::Uint16x2(source)) => {
525
this.push(source[i]);
526
}
527
(VertexAttributeValues::Uint16x2(_), _) => panic!("Mismatched vertex attribute values"),
528
(VertexAttributeValues::Unorm16x2(this), VertexAttributeValues::Unorm16x2(source)) => {
529
this.push(source[i]);
530
}
531
(VertexAttributeValues::Unorm16x2(_), _) => {
532
panic!("Mismatched vertex attribute values")
533
}
534
(VertexAttributeValues::Sint16x4(this), VertexAttributeValues::Sint16x4(source)) => {
535
this.push(source[i]);
536
}
537
(VertexAttributeValues::Sint16x4(_), _) => panic!("Mismatched vertex attribute values"),
538
(VertexAttributeValues::Snorm16x4(this), VertexAttributeValues::Snorm16x4(source)) => {
539
this.push(source[i]);
540
}
541
(VertexAttributeValues::Snorm16x4(_), _) => {
542
panic!("Mismatched vertex attribute values")
543
}
544
(VertexAttributeValues::Uint16x4(this), VertexAttributeValues::Uint16x4(source)) => {
545
this.push(source[i]);
546
}
547
(VertexAttributeValues::Uint16x4(_), _) => panic!("Mismatched vertex attribute values"),
548
(VertexAttributeValues::Unorm16x4(this), VertexAttributeValues::Unorm16x4(source)) => {
549
this.push(source[i]);
550
}
551
(VertexAttributeValues::Unorm16x4(_), _) => {
552
panic!("Mismatched vertex attribute values")
553
}
554
(VertexAttributeValues::Sint8x2(this), VertexAttributeValues::Sint8x2(source)) => {
555
this.push(source[i]);
556
}
557
(VertexAttributeValues::Sint8x2(_), _) => panic!("Mismatched vertex attribute values"),
558
(VertexAttributeValues::Snorm8x2(this), VertexAttributeValues::Snorm8x2(source)) => {
559
this.push(source[i]);
560
}
561
(VertexAttributeValues::Snorm8x2(_), _) => panic!("Mismatched vertex attribute values"),
562
(VertexAttributeValues::Uint8x2(this), VertexAttributeValues::Uint8x2(source)) => {
563
this.push(source[i]);
564
}
565
(VertexAttributeValues::Uint8x2(_), _) => panic!("Mismatched vertex attribute values"),
566
(VertexAttributeValues::Unorm8x2(this), VertexAttributeValues::Unorm8x2(source)) => {
567
this.push(source[i]);
568
}
569
(VertexAttributeValues::Unorm8x2(_), _) => panic!("Mismatched vertex attribute values"),
570
(VertexAttributeValues::Sint8x4(this), VertexAttributeValues::Sint8x4(source)) => {
571
this.push(source[i]);
572
}
573
(VertexAttributeValues::Sint8x4(_), _) => panic!("Mismatched vertex attribute values"),
574
(VertexAttributeValues::Snorm8x4(this), VertexAttributeValues::Snorm8x4(source)) => {
575
this.push(source[i]);
576
}
577
(VertexAttributeValues::Snorm8x4(_), _) => panic!("Mismatched vertex attribute values"),
578
(VertexAttributeValues::Uint8x4(this), VertexAttributeValues::Uint8x4(source)) => {
579
this.push(source[i]);
580
}
581
(VertexAttributeValues::Uint8x4(_), _) => panic!("Mismatched vertex attribute values"),
582
(VertexAttributeValues::Unorm8x4(this), VertexAttributeValues::Unorm8x4(source)) => {
583
this.push(source[i]);
584
}
585
(VertexAttributeValues::Unorm8x4(_), _) => panic!("Mismatched vertex attribute values"),
586
}
587
}
588
589
#[expect(
590
clippy::match_same_arms,
591
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."
592
)]
593
pub(crate) fn shrink_to_fit(&mut self) {
594
match self {
595
VertexAttributeValues::Float32(v) => v.shrink_to_fit(),
596
VertexAttributeValues::Sint32(v) => v.shrink_to_fit(),
597
VertexAttributeValues::Uint32(v) => v.shrink_to_fit(),
598
VertexAttributeValues::Float32x2(v) => v.shrink_to_fit(),
599
VertexAttributeValues::Sint32x2(v) => v.shrink_to_fit(),
600
VertexAttributeValues::Uint32x2(v) => v.shrink_to_fit(),
601
VertexAttributeValues::Float32x3(v) => v.shrink_to_fit(),
602
VertexAttributeValues::Sint32x3(v) => v.shrink_to_fit(),
603
VertexAttributeValues::Uint32x3(v) => v.shrink_to_fit(),
604
VertexAttributeValues::Float32x4(v) => v.shrink_to_fit(),
605
VertexAttributeValues::Sint32x4(v) => v.shrink_to_fit(),
606
VertexAttributeValues::Uint32x4(v) => v.shrink_to_fit(),
607
VertexAttributeValues::Sint16x2(v) => v.shrink_to_fit(),
608
VertexAttributeValues::Snorm16x2(v) => v.shrink_to_fit(),
609
VertexAttributeValues::Uint16x2(v) => v.shrink_to_fit(),
610
VertexAttributeValues::Unorm16x2(v) => v.shrink_to_fit(),
611
VertexAttributeValues::Sint16x4(v) => v.shrink_to_fit(),
612
VertexAttributeValues::Snorm16x4(v) => v.shrink_to_fit(),
613
VertexAttributeValues::Uint16x4(v) => v.shrink_to_fit(),
614
VertexAttributeValues::Unorm16x4(v) => v.shrink_to_fit(),
615
VertexAttributeValues::Sint8x2(v) => v.shrink_to_fit(),
616
VertexAttributeValues::Snorm8x2(v) => v.shrink_to_fit(),
617
VertexAttributeValues::Uint8x2(v) => v.shrink_to_fit(),
618
VertexAttributeValues::Unorm8x2(v) => v.shrink_to_fit(),
619
VertexAttributeValues::Sint8x4(v) => v.shrink_to_fit(),
620
VertexAttributeValues::Snorm8x4(v) => v.shrink_to_fit(),
621
VertexAttributeValues::Uint8x4(v) => v.shrink_to_fit(),
622
VertexAttributeValues::Unorm8x4(v) => v.shrink_to_fit(),
623
}
624
}
625
}
626
627
impl From<&VertexAttributeValues> for VertexFormat {
628
fn from(values: &VertexAttributeValues) -> Self {
629
match values {
630
VertexAttributeValues::Float32(_) => VertexFormat::Float32,
631
VertexAttributeValues::Sint32(_) => VertexFormat::Sint32,
632
VertexAttributeValues::Uint32(_) => VertexFormat::Uint32,
633
VertexAttributeValues::Float32x2(_) => VertexFormat::Float32x2,
634
VertexAttributeValues::Sint32x2(_) => VertexFormat::Sint32x2,
635
VertexAttributeValues::Uint32x2(_) => VertexFormat::Uint32x2,
636
VertexAttributeValues::Float32x3(_) => VertexFormat::Float32x3,
637
VertexAttributeValues::Sint32x3(_) => VertexFormat::Sint32x3,
638
VertexAttributeValues::Uint32x3(_) => VertexFormat::Uint32x3,
639
VertexAttributeValues::Float32x4(_) => VertexFormat::Float32x4,
640
VertexAttributeValues::Sint32x4(_) => VertexFormat::Sint32x4,
641
VertexAttributeValues::Uint32x4(_) => VertexFormat::Uint32x4,
642
VertexAttributeValues::Sint16x2(_) => VertexFormat::Sint16x2,
643
VertexAttributeValues::Snorm16x2(_) => VertexFormat::Snorm16x2,
644
VertexAttributeValues::Uint16x2(_) => VertexFormat::Uint16x2,
645
VertexAttributeValues::Unorm16x2(_) => VertexFormat::Unorm16x2,
646
VertexAttributeValues::Sint16x4(_) => VertexFormat::Sint16x4,
647
VertexAttributeValues::Snorm16x4(_) => VertexFormat::Snorm16x4,
648
VertexAttributeValues::Uint16x4(_) => VertexFormat::Uint16x4,
649
VertexAttributeValues::Unorm16x4(_) => VertexFormat::Unorm16x4,
650
VertexAttributeValues::Sint8x2(_) => VertexFormat::Sint8x2,
651
VertexAttributeValues::Snorm8x2(_) => VertexFormat::Snorm8x2,
652
VertexAttributeValues::Uint8x2(_) => VertexFormat::Uint8x2,
653
VertexAttributeValues::Unorm8x2(_) => VertexFormat::Unorm8x2,
654
VertexAttributeValues::Sint8x4(_) => VertexFormat::Sint8x4,
655
VertexAttributeValues::Snorm8x4(_) => VertexFormat::Snorm8x4,
656
VertexAttributeValues::Uint8x4(_) => VertexFormat::Uint8x4,
657
VertexAttributeValues::Unorm8x4(_) => VertexFormat::Unorm8x4,
658
}
659
}
660
}
661
662
/// Describes how the vertex buffer is interpreted.
663
#[derive(Default, Clone, Debug, Hash, Eq, PartialEq)]
664
pub struct VertexBufferLayout {
665
/// The stride, in bytes, between elements of this buffer.
666
pub array_stride: BufferAddress,
667
/// How often this vertex buffer is "stepped" forward.
668
pub step_mode: VertexStepMode,
669
/// The list of attributes which comprise a single vertex.
670
pub attributes: Vec<VertexAttribute>,
671
}
672
673
impl VertexBufferLayout {
674
/// Creates a new densely packed [`VertexBufferLayout`] from an iterator of vertex formats.
675
/// Iteration order determines the `shader_location` and `offset` of the [`VertexAttributes`](VertexAttribute).
676
/// The first iterated item will have a `shader_location` and `offset` of zero.
677
/// The `array_stride` is the sum of the size of the iterated [`VertexFormats`](VertexFormat) (in bytes).
678
pub fn from_vertex_formats<T: IntoIterator<Item = VertexFormat>>(
679
step_mode: VertexStepMode,
680
vertex_formats: T,
681
) -> Self {
682
let mut offset = 0;
683
let mut attributes = Vec::new();
684
for (shader_location, format) in vertex_formats.into_iter().enumerate() {
685
attributes.push(VertexAttribute {
686
format,
687
offset,
688
shader_location: shader_location as u32,
689
});
690
offset += format.size();
691
}
692
693
VertexBufferLayout {
694
array_stride: offset,
695
step_mode,
696
attributes,
697
}
698
}
699
700
/// Returns a [`VertexBufferLayout`] with the shader location of every attribute offset by
701
/// `location`.
702
pub fn offset_locations_by(mut self, location: u32) -> Self {
703
self.attributes.iter_mut().for_each(|attr| {
704
attr.shader_location += location;
705
});
706
self
707
}
708
}
709
710
/// Describes the layout of the mesh vertices in GPU memory.
711
///
712
/// At most one copy of a mesh vertex buffer layout ever exists in GPU memory at
713
/// once. Therefore, comparing these for equality requires only a single pointer
714
/// comparison, and this type's [`PartialEq`] and [`Hash`] implementations take
715
/// advantage of this. To that end, this type doesn't implement
716
/// [`bevy_derive::Deref`] or [`bevy_derive::DerefMut`] in order to reduce the
717
/// possibility of accidental deep comparisons, which would be needlessly
718
/// expensive.
719
#[derive(Clone, Debug)]
720
pub struct MeshVertexBufferLayoutRef(pub Arc<MeshVertexBufferLayout>);
721
722
/// Stores the single copy of each mesh vertex buffer layout.
723
#[derive(Clone, Default, Resource)]
724
pub struct MeshVertexBufferLayouts(HashSet<Arc<MeshVertexBufferLayout>>);
725
726
impl MeshVertexBufferLayouts {
727
/// Inserts a new mesh vertex buffer layout in the store and returns a
728
/// reference to it, reusing the existing reference if this mesh vertex
729
/// buffer layout was already in the store.
730
pub fn insert(&mut self, layout: MeshVertexBufferLayout) -> MeshVertexBufferLayoutRef {
731
// Because the special `PartialEq` and `Hash` implementations that
732
// compare by pointer are on `MeshVertexBufferLayoutRef`, not on
733
// `Arc<MeshVertexBufferLayout>`, this compares the mesh vertex buffer
734
// structurally, not by pointer.
735
MeshVertexBufferLayoutRef(
736
self.0
737
.get_or_insert_with(&layout, |layout| Arc::new(layout.clone()))
738
.clone(),
739
)
740
}
741
}
742
743
impl PartialEq for MeshVertexBufferLayoutRef {
744
fn eq(&self, other: &Self) -> bool {
745
Arc::ptr_eq(&self.0, &other.0)
746
}
747
}
748
749
impl Eq for MeshVertexBufferLayoutRef {}
750
751
impl Hash for MeshVertexBufferLayoutRef {
752
fn hash<H: Hasher>(&self, state: &mut H) {
753
// Hash the address of the underlying data, so two layouts that share the same
754
// `MeshVertexBufferLayout` will have the same hash.
755
(Arc::as_ptr(&self.0) as usize).hash(state);
756
}
757
}
758
759