Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_render/src/mesh/mod.rs
6596 views
1
pub mod allocator;
2
use crate::{
3
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
4
render_resource::TextureView,
5
texture::GpuImage,
6
RenderApp,
7
};
8
use allocator::MeshAllocatorPlugin;
9
use bevy_app::{App, Plugin, PostUpdate};
10
use bevy_asset::{AssetApp, AssetId, RenderAssetUsages};
11
use bevy_ecs::{
12
prelude::*,
13
system::{
14
lifetimeless::{SRes, SResMut},
15
SystemParamItem,
16
},
17
};
18
use bevy_mesh::morph::{MeshMorphWeights, MorphWeights};
19
use bevy_mesh::*;
20
use wgpu::IndexFormat;
21
22
/// Adds the [`Mesh`] as an asset and makes sure that they are extracted and prepared for the GPU.
23
pub struct MeshPlugin;
24
25
impl Plugin for MeshPlugin {
26
fn build(&self, app: &mut App) {
27
app.init_asset::<skinning::SkinnedMeshInverseBindposes>()
28
// 'Mesh' must be prepared after 'Image' as meshes rely on the morph target image being ready
29
.add_plugins(RenderAssetPlugin::<RenderMesh, GpuImage>::default())
30
.add_plugins(MeshAllocatorPlugin);
31
32
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
33
return;
34
};
35
36
render_app.init_resource::<MeshVertexBufferLayouts>();
37
}
38
}
39
40
/// [Inherit weights](inherit_weights) from glTF mesh parent entity to direct
41
/// bevy mesh child entities (ie: glTF primitive).
42
pub struct MorphPlugin;
43
impl Plugin for MorphPlugin {
44
fn build(&self, app: &mut App) {
45
app.add_systems(PostUpdate, inherit_weights.in_set(InheritWeightSystems));
46
}
47
}
48
49
/// Bevy meshes are gltf primitives, [`MorphWeights`] on the bevy node entity
50
/// should be inherited by children meshes.
51
///
52
/// Only direct children are updated, to fulfill the expectations of glTF spec.
53
pub fn inherit_weights(
54
morph_nodes: Query<(&Children, &MorphWeights), (Without<Mesh3d>, Changed<MorphWeights>)>,
55
mut morph_primitives: Query<&mut MeshMorphWeights, With<Mesh3d>>,
56
) {
57
for (children, parent_weights) in &morph_nodes {
58
let mut iter = morph_primitives.iter_many_mut(children);
59
while let Some(mut child_weight) = iter.fetch_next() {
60
child_weight.clear_weights();
61
child_weight.extend_weights(parent_weights.weights());
62
}
63
}
64
}
65
66
/// The render world representation of a [`Mesh`].
67
#[derive(Debug, Clone)]
68
pub struct RenderMesh {
69
/// The number of vertices in the mesh.
70
pub vertex_count: u32,
71
72
/// Morph targets for the mesh, if present.
73
pub morph_targets: Option<TextureView>,
74
75
/// Information about the mesh data buffers, including whether the mesh uses
76
/// indices or not.
77
pub buffer_info: RenderMeshBufferInfo,
78
79
/// Precomputed pipeline key bits for this mesh.
80
pub key_bits: BaseMeshPipelineKey,
81
82
/// A reference to the vertex buffer layout.
83
///
84
/// Combined with [`RenderMesh::buffer_info`], this specifies the complete
85
/// layout of the buffers associated with this mesh.
86
pub layout: MeshVertexBufferLayoutRef,
87
}
88
89
impl RenderMesh {
90
/// Returns the primitive topology of this mesh (triangles, triangle strips,
91
/// etc.)
92
#[inline]
93
pub fn primitive_topology(&self) -> PrimitiveTopology {
94
self.key_bits.primitive_topology()
95
}
96
97
/// Returns true if this mesh uses an index buffer or false otherwise.
98
#[inline]
99
pub fn indexed(&self) -> bool {
100
matches!(self.buffer_info, RenderMeshBufferInfo::Indexed { .. })
101
}
102
}
103
104
/// The index/vertex buffer info of a [`RenderMesh`].
105
#[derive(Debug, Clone)]
106
pub enum RenderMeshBufferInfo {
107
Indexed {
108
count: u32,
109
index_format: IndexFormat,
110
},
111
NonIndexed,
112
}
113
114
impl RenderAsset for RenderMesh {
115
type SourceAsset = Mesh;
116
type Param = (
117
SRes<RenderAssets<GpuImage>>,
118
SResMut<MeshVertexBufferLayouts>,
119
);
120
121
#[inline]
122
fn asset_usage(mesh: &Self::SourceAsset) -> RenderAssetUsages {
123
mesh.asset_usage
124
}
125
126
fn byte_len(mesh: &Self::SourceAsset) -> Option<usize> {
127
let mut vertex_size = 0;
128
for attribute_data in mesh.attributes() {
129
let vertex_format = attribute_data.0.format;
130
vertex_size += vertex_format.size() as usize;
131
}
132
133
let vertex_count = mesh.count_vertices();
134
let index_bytes = mesh.get_index_buffer_bytes().map(<[_]>::len).unwrap_or(0);
135
Some(vertex_size * vertex_count + index_bytes)
136
}
137
138
/// Converts the extracted mesh into a [`RenderMesh`].
139
fn prepare_asset(
140
mesh: Self::SourceAsset,
141
_: AssetId<Self::SourceAsset>,
142
(images, mesh_vertex_buffer_layouts): &mut SystemParamItem<Self::Param>,
143
_: Option<&Self>,
144
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
145
let morph_targets = match mesh.morph_targets() {
146
Some(mt) => {
147
let Some(target_image) = images.get(mt) else {
148
return Err(PrepareAssetError::RetryNextUpdate(mesh));
149
};
150
Some(target_image.texture_view.clone())
151
}
152
None => None,
153
};
154
155
let buffer_info = match mesh.indices() {
156
Some(indices) => RenderMeshBufferInfo::Indexed {
157
count: indices.len() as u32,
158
index_format: indices.into(),
159
},
160
None => RenderMeshBufferInfo::NonIndexed,
161
};
162
163
let mesh_vertex_buffer_layout =
164
mesh.get_mesh_vertex_buffer_layout(mesh_vertex_buffer_layouts);
165
166
let mut key_bits = BaseMeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
167
key_bits.set(
168
BaseMeshPipelineKey::MORPH_TARGETS,
169
mesh.morph_targets().is_some(),
170
);
171
172
Ok(RenderMesh {
173
vertex_count: mesh.count_vertices() as u32,
174
buffer_info,
175
key_bits,
176
layout: mesh_vertex_buffer_layout,
177
morph_targets,
178
})
179
}
180
}
181
182