1use bevy_math::Vec3;
2pub use bevy_mesh::*;
3use morph::{MeshMorphWeights, MorphWeights};
4pub mod allocator;
5mod components;
6use crate::{
7 primitives::Aabb,
8 render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
9 render_resource::TextureView,
10 texture::GpuImage,
11 view::VisibilitySystems,
12 RenderApp,
13};
14use allocator::MeshAllocatorPlugin;
15use bevy_app::{App, Plugin, PostUpdate};
16use bevy_asset::{AssetApp, AssetEvents, AssetId, RenderAssetUsages};
17use bevy_ecs::{
18 prelude::*,
19 system::{
20 lifetimeless::{SRes, SResMut},
21 SystemParamItem,
22 },
23};
24pub use components::{mark_3d_meshes_as_changed_if_their_assets_changed, Mesh2d, Mesh3d, MeshTag};
25use wgpu::IndexFormat;
26
27pub struct MeshBuildersPlugin;
29
30impl Plugin for MeshBuildersPlugin {
31 fn build(&self, app: &mut App) {
32 app.register_type::<CircleMeshBuilder>()
34 .register_type::<CircularSectorMeshBuilder>()
35 .register_type::<CircularSegmentMeshBuilder>()
36 .register_type::<RegularPolygonMeshBuilder>()
37 .register_type::<EllipseMeshBuilder>()
38 .register_type::<AnnulusMeshBuilder>()
39 .register_type::<RhombusMeshBuilder>()
40 .register_type::<Triangle2dMeshBuilder>()
41 .register_type::<RectangleMeshBuilder>()
42 .register_type::<Capsule2dMeshBuilder>()
43 .register_type::<Capsule3dMeshBuilder>()
45 .register_type::<ConeMeshBuilder>()
46 .register_type::<ConicalFrustumMeshBuilder>()
47 .register_type::<CuboidMeshBuilder>()
48 .register_type::<CylinderMeshBuilder>()
49 .register_type::<PlaneMeshBuilder>()
50 .register_type::<SphereMeshBuilder>()
51 .register_type::<TetrahedronMeshBuilder>()
52 .register_type::<TorusMeshBuilder>()
53 .register_type::<Triangle3dMeshBuilder>();
54 }
55}
56
57pub struct MeshPlugin;
59
60impl Plugin for MeshPlugin {
61 fn build(&self, app: &mut App) {
62 app.init_asset::<Mesh>()
63 .init_asset::<skinning::SkinnedMeshInverseBindposes>()
64 .register_asset_reflect::<Mesh>()
65 .register_type::<Mesh3d>()
66 .register_type::<skinning::SkinnedMesh>()
67 .register_type::<Vec<Entity>>()
68 .add_plugins(MeshBuildersPlugin)
69 .add_plugins(RenderAssetPlugin::<RenderMesh, GpuImage>::default())
71 .add_plugins(MeshAllocatorPlugin)
72 .add_systems(
73 PostUpdate,
74 mark_3d_meshes_as_changed_if_their_assets_changed
75 .ambiguous_with(VisibilitySystems::CalculateBounds)
76 .before(AssetEvents),
77 );
78
79 let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
80 return;
81 };
82
83 render_app.init_resource::<MeshVertexBufferLayouts>();
84 }
85}
86
87pub struct MorphPlugin;
90impl Plugin for MorphPlugin {
91 fn build(&self, app: &mut App) {
92 app.register_type::<MorphWeights>()
93 .register_type::<MeshMorphWeights>()
94 .add_systems(PostUpdate, inherit_weights);
95 }
96}
97
98pub fn inherit_weights(
103 morph_nodes: Query<(&Children, &MorphWeights), (Without<Mesh3d>, Changed<MorphWeights>)>,
104 mut morph_primitives: Query<&mut MeshMorphWeights, With<Mesh3d>>,
105) {
106 for (children, parent_weights) in &morph_nodes {
107 let mut iter = morph_primitives.iter_many_mut(children);
108 while let Some(mut child_weight) = iter.fetch_next() {
109 child_weight.clear_weights();
110 child_weight.extend_weights(parent_weights.weights());
111 }
112 }
113}
114
115pub trait MeshAabb {
116 fn compute_aabb(&self) -> Option<Aabb>;
121}
122
123impl MeshAabb for Mesh {
124 fn compute_aabb(&self) -> Option<Aabb> {
125 let Some(VertexAttributeValues::Float32x3(values)) =
126 self.attribute(Mesh::ATTRIBUTE_POSITION)
127 else {
128 return None;
129 };
130
131 Aabb::enclosing(values.iter().map(|p| Vec3::from_slice(p)))
132 }
133}
134
135#[derive(Debug, Clone)]
137pub struct RenderMesh {
138 pub vertex_count: u32,
140
141 pub morph_targets: Option<TextureView>,
143
144 pub buffer_info: RenderMeshBufferInfo,
147
148 pub key_bits: BaseMeshPipelineKey,
150
151 pub layout: MeshVertexBufferLayoutRef,
156}
157
158impl RenderMesh {
159 #[inline]
162 pub fn primitive_topology(&self) -> PrimitiveTopology {
163 self.key_bits.primitive_topology()
164 }
165
166 #[inline]
168 pub fn indexed(&self) -> bool {
169 matches!(self.buffer_info, RenderMeshBufferInfo::Indexed { .. })
170 }
171}
172
173#[derive(Debug, Clone)]
175pub enum RenderMeshBufferInfo {
176 Indexed {
177 count: u32,
178 index_format: IndexFormat,
179 },
180 NonIndexed,
181}
182
183impl RenderAsset for RenderMesh {
184 type SourceAsset = Mesh;
185 type Param = (
186 SRes<RenderAssets<GpuImage>>,
187 SResMut<MeshVertexBufferLayouts>,
188 );
189
190 #[inline]
191 fn asset_usage(mesh: &Self::SourceAsset) -> RenderAssetUsages {
192 mesh.asset_usage
193 }
194
195 fn byte_len(mesh: &Self::SourceAsset) -> Option<usize> {
196 let mut vertex_size = 0;
197 for attribute_data in mesh.attributes() {
198 let vertex_format = attribute_data.0.format;
199 vertex_size += vertex_format.size() as usize;
200 }
201
202 let vertex_count = mesh.count_vertices();
203 let index_bytes = mesh.get_index_buffer_bytes().map(<[_]>::len).unwrap_or(0);
204 Some(vertex_size * vertex_count + index_bytes)
205 }
206
207 fn prepare_asset(
209 mesh: Self::SourceAsset,
210 _: AssetId<Self::SourceAsset>,
211 (images, mesh_vertex_buffer_layouts): &mut SystemParamItem<Self::Param>,
212 ) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
213 let morph_targets = match mesh.morph_targets() {
214 Some(mt) => {
215 let Some(target_image) = images.get(mt) else {
216 return Err(PrepareAssetError::RetryNextUpdate(mesh));
217 };
218 Some(target_image.texture_view.clone())
219 }
220 None => None,
221 };
222
223 let buffer_info = match mesh.indices() {
224 Some(indices) => RenderMeshBufferInfo::Indexed {
225 count: indices.len() as u32,
226 index_format: indices.into(),
227 },
228 None => RenderMeshBufferInfo::NonIndexed,
229 };
230
231 let mesh_vertex_buffer_layout =
232 mesh.get_mesh_vertex_buffer_layout(mesh_vertex_buffer_layouts);
233
234 let mut key_bits = BaseMeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
235 key_bits.set(
236 BaseMeshPipelineKey::MORPH_TARGETS,
237 mesh.morph_targets().is_some(),
238 );
239
240 Ok(RenderMesh {
241 vertex_count: mesh.count_vertices() as u32,
242 buffer_info,
243 key_bits,
244 layout: mesh_vertex_buffer_layout,
245 morph_targets,
246 })
247 }
248}