1use bevy_hierarchy::Children;
2use bevy_math::Vec3;
3pub use bevy_mesh::*;
4use morph::{MeshMorphWeights, MorphWeights};
5pub mod allocator;
6mod components;
7use crate::{
8 primitives::Aabb,
9 render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
10 render_resource::TextureView,
11 texture::GpuImage,
12 RenderApp,
13};
14use allocator::MeshAllocatorPlugin;
15use bevy_app::{App, Plugin, PostUpdate};
16use bevy_asset::{AssetApp, RenderAssetUsages};
17use bevy_ecs::{
18 entity::Entity,
19 query::{Changed, With},
20 system::Query,
21};
22use bevy_ecs::{
23 query::Without,
24 system::{
25 lifetimeless::{SRes, SResMut},
26 SystemParamItem,
27 },
28};
29pub use components::{Mesh2d, Mesh3d};
30use wgpu::IndexFormat;
31
32pub struct MeshPlugin;
34
35impl Plugin for MeshPlugin {
36 fn build(&self, app: &mut App) {
37 app.init_asset::<Mesh>()
38 .init_asset::<skinning::SkinnedMeshInverseBindposes>()
39 .register_asset_reflect::<Mesh>()
40 .register_type::<Mesh3d>()
41 .register_type::<skinning::SkinnedMesh>()
42 .register_type::<Vec<Entity>>()
43 .add_plugins(RenderAssetPlugin::<RenderMesh, GpuImage>::default())
45 .add_plugins(MeshAllocatorPlugin);
46
47 let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
48 return;
49 };
50
51 render_app.init_resource::<MeshVertexBufferLayouts>();
52 }
53}
54
55pub struct MorphPlugin;
58impl Plugin for MorphPlugin {
59 fn build(&self, app: &mut App) {
60 app.register_type::<MorphWeights>()
61 .register_type::<MeshMorphWeights>()
62 .add_systems(PostUpdate, inherit_weights);
63 }
64}
65
66pub fn inherit_weights(
71 morph_nodes: Query<(&Children, &MorphWeights), (Without<Mesh3d>, Changed<MorphWeights>)>,
72 mut morph_primitives: Query<&mut MeshMorphWeights, With<Mesh3d>>,
73) {
74 for (children, parent_weights) in &morph_nodes {
75 let mut iter = morph_primitives.iter_many_mut(children);
76 while let Some(mut child_weight) = iter.fetch_next() {
77 child_weight.clear_weights();
78 child_weight.extend_weights(parent_weights.weights());
79 }
80 }
81}
82
83pub trait MeshAabb {
84 fn compute_aabb(&self) -> Option<Aabb>;
89}
90
91impl MeshAabb for Mesh {
92 fn compute_aabb(&self) -> Option<Aabb> {
93 let Some(VertexAttributeValues::Float32x3(values)) =
94 self.attribute(Mesh::ATTRIBUTE_POSITION)
95 else {
96 return None;
97 };
98
99 Aabb::enclosing(values.iter().map(|p| Vec3::from_slice(p)))
100 }
101}
102
103#[derive(Debug, Clone)]
105pub struct RenderMesh {
106 pub vertex_count: u32,
108
109 pub morph_targets: Option<TextureView>,
111
112 pub buffer_info: RenderMeshBufferInfo,
115
116 pub key_bits: BaseMeshPipelineKey,
118
119 pub layout: MeshVertexBufferLayoutRef,
124}
125
126impl RenderMesh {
127 #[inline]
130 pub fn primitive_topology(&self) -> PrimitiveTopology {
131 self.key_bits.primitive_topology()
132 }
133}
134
135#[derive(Debug, Clone)]
137pub enum RenderMeshBufferInfo {
138 Indexed {
139 count: u32,
140 index_format: IndexFormat,
141 },
142 NonIndexed,
143}
144
145impl RenderAsset for RenderMesh {
146 type SourceAsset = Mesh;
147 type Param = (
148 SRes<RenderAssets<GpuImage>>,
149 SResMut<MeshVertexBufferLayouts>,
150 );
151
152 #[inline]
153 fn asset_usage(mesh: &Self::SourceAsset) -> RenderAssetUsages {
154 mesh.asset_usage
155 }
156
157 fn byte_len(mesh: &Self::SourceAsset) -> Option<usize> {
158 let mut vertex_size = 0;
159 for attribute_data in mesh.attributes() {
160 let vertex_format = attribute_data.0.format;
161 vertex_size += vertex_format.get_size() as usize;
162 }
163
164 let vertex_count = mesh.count_vertices();
165 let index_bytes = mesh.get_index_buffer_bytes().map(<[_]>::len).unwrap_or(0);
166 Some(vertex_size * vertex_count + index_bytes)
167 }
168
169 fn prepare_asset(
171 mesh: Self::SourceAsset,
172 (images, ref mut mesh_vertex_buffer_layouts): &mut SystemParamItem<Self::Param>,
173 ) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
174 let morph_targets = match mesh.morph_targets() {
175 Some(mt) => {
176 let Some(target_image) = images.get(mt) else {
177 return Err(PrepareAssetError::RetryNextUpdate(mesh));
178 };
179 Some(target_image.texture_view.clone())
180 }
181 None => None,
182 };
183
184 let buffer_info = match mesh.indices() {
185 Some(indices) => RenderMeshBufferInfo::Indexed {
186 count: indices.len() as u32,
187 index_format: indices.into(),
188 },
189 None => RenderMeshBufferInfo::NonIndexed,
190 };
191
192 let mesh_vertex_buffer_layout =
193 mesh.get_mesh_vertex_buffer_layout(mesh_vertex_buffer_layouts);
194
195 let mut key_bits = BaseMeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
196 key_bits.set(
197 BaseMeshPipelineKey::MORPH_TARGETS,
198 mesh.morph_targets().is_some(),
199 );
200
201 Ok(RenderMesh {
202 vertex_count: mesh.count_vertices() as u32,
203 buffer_info,
204 key_bits,
205 layout: mesh_vertex_buffer_layout,
206 morph_targets,
207 })
208 }
209}