1pub mod allocator;
2use crate::{
3 render_asset::{
4 AssetExtractionError, PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets,
5 },
6 texture::GpuImage,
7 RenderApp,
8};
9use allocator::MeshAllocatorPlugin;
10use bevy_app::{App, Plugin};
11use bevy_asset::{AssetId, RenderAssetUsages};
12use bevy_ecs::{
13 prelude::*,
14 system::{
15 lifetimeless::{SRes, SResMut},
16 SystemParamItem,
17 },
18};
19#[cfg(feature = "morph")]
20use bevy_mesh::morph::{MeshMorphWeights, MorphWeights};
21use bevy_mesh::*;
22use wgpu::IndexFormat;
23
24pub struct MeshRenderAssetPlugin;
27
28impl Plugin for MeshRenderAssetPlugin {
29 fn build(&self, app: &mut App) {
30 app
31 .add_plugins(RenderAssetPlugin::<RenderMesh, GpuImage>::default())
33 .add_plugins(MeshAllocatorPlugin);
34
35 let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
36 return;
37 };
38
39 render_app.init_resource::<MeshVertexBufferLayouts>();
40 }
41}
42
43#[cfg(feature = "morph")]
46pub struct MorphPlugin;
47#[cfg(feature = "morph")]
48impl Plugin for MorphPlugin {
49 fn build(&self, app: &mut App) {
50 app.add_systems(
51 bevy_app::PostUpdate,
52 inherit_weights.in_set(InheritWeightSystems),
53 );
54 }
55}
56
57#[cfg(feature = "morph")]
62pub fn inherit_weights(
63 morph_nodes: Query<(&Children, &MorphWeights), (Without<Mesh3d>, Changed<MorphWeights>)>,
64 mut morph_primitives: Query<&mut MeshMorphWeights, With<Mesh3d>>,
65) {
66 for (children, parent_weights) in &morph_nodes {
67 let mut iter = morph_primitives.iter_many_mut(children);
68 while let Some(mut child_weight) = iter.fetch_next() {
69 child_weight.clear_weights();
70 child_weight.extend_weights(parent_weights.weights());
71 }
72 }
73}
74
75#[derive(Debug, Clone)]
77pub struct RenderMesh {
78 pub vertex_count: u32,
80
81 #[cfg(feature = "morph")]
83 pub morph_targets: Option<crate::render_resource::TextureView>,
84
85 pub buffer_info: RenderMeshBufferInfo,
88
89 pub key_bits: BaseMeshPipelineKey,
91
92 pub layout: MeshVertexBufferLayoutRef,
97}
98
99impl RenderMesh {
100 #[inline]
103 pub fn primitive_topology(&self) -> PrimitiveTopology {
104 self.key_bits.primitive_topology()
105 }
106
107 #[inline]
109 pub fn indexed(&self) -> bool {
110 matches!(self.buffer_info, RenderMeshBufferInfo::Indexed { .. })
111 }
112}
113
114#[derive(Debug, Clone)]
116pub enum RenderMeshBufferInfo {
117 Indexed {
118 count: u32,
119 index_format: IndexFormat,
120 },
121 NonIndexed,
122}
123
124impl RenderAsset for RenderMesh {
125 type SourceAsset = Mesh;
126 type Param = (
127 SRes<RenderAssets<GpuImage>>,
128 SResMut<MeshVertexBufferLayouts>,
129 );
130
131 #[inline]
132 fn asset_usage(mesh: &Self::SourceAsset) -> RenderAssetUsages {
133 mesh.asset_usage
134 }
135
136 fn take_gpu_data(
137 source: &mut Self::SourceAsset,
138 _previous_gpu_asset: Option<&Self>,
139 ) -> Result<Self::SourceAsset, AssetExtractionError> {
140 source
141 .take_gpu_data()
142 .map_err(|_| AssetExtractionError::AlreadyExtracted)
143 }
144
145 fn byte_len(mesh: &Self::SourceAsset) -> Option<usize> {
146 let mut vertex_size = 0;
147 for attribute_data in mesh.attributes() {
148 let vertex_format = attribute_data.0.format;
149 vertex_size += vertex_format.size() as usize;
150 }
151
152 let vertex_count = mesh.count_vertices();
153 let index_bytes = mesh.get_index_buffer_bytes().map(<[_]>::len).unwrap_or(0);
154 Some(vertex_size * vertex_count + index_bytes)
155 }
156
157 fn prepare_asset(
159 mesh: Self::SourceAsset,
160 _: AssetId<Self::SourceAsset>,
161 (_images, mesh_vertex_buffer_layouts): &mut SystemParamItem<Self::Param>,
162 _: Option<&Self>,
163 ) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
164 #[cfg(feature = "morph")]
165 let morph_targets = match mesh.morph_targets() {
166 Some(mt) => {
167 let Some(target_image) = _images.get(mt) else {
168 return Err(PrepareAssetError::RetryNextUpdate(mesh));
169 };
170 Some(target_image.texture_view.clone())
171 }
172 None => None,
173 };
174
175 let buffer_info = match mesh.indices() {
176 Some(indices) => RenderMeshBufferInfo::Indexed {
177 count: indices.len() as u32,
178 index_format: indices.into(),
179 },
180 None => RenderMeshBufferInfo::NonIndexed,
181 };
182
183 let mesh_vertex_buffer_layout =
184 mesh.get_mesh_vertex_buffer_layout(mesh_vertex_buffer_layouts);
185
186 let key_bits = BaseMeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
187 #[cfg(feature = "morph")]
188 let key_bits = if mesh.morph_targets().is_some() {
189 key_bits | BaseMeshPipelineKey::MORPH_TARGETS
190 } else {
191 key_bits
192 };
193
194 Ok(RenderMesh {
195 vertex_count: mesh.count_vertices() as u32,
196 buffer_info,
197 key_bits,
198 layout: mesh_vertex_buffer_layout,
199 #[cfg(feature = "morph")]
200 morph_targets,
201 })
202 }
203}