bevy_render/mesh/
mod.rs

1#[allow(clippy::module_inception)]
2mod mesh;
3pub mod morph;
4pub mod primitives;
5
6use bevy_utils::HashSet;
7pub use mesh::*;
8pub use primitives::*;
9use std::{
10    hash::{Hash, Hasher},
11    sync::Arc,
12};
13
14use crate::{render_asset::RenderAssetPlugin, texture::GpuImage, RenderApp};
15use bevy_app::{App, Plugin};
16use bevy_asset::AssetApp;
17use bevy_ecs::{entity::Entity, system::Resource};
18
19/// Adds the [`Mesh`] as an asset and makes sure that they are extracted and prepared for the GPU.
20pub struct MeshPlugin;
21
22impl Plugin for MeshPlugin {
23    fn build(&self, app: &mut App) {
24        app.init_asset::<Mesh>()
25            .init_asset::<skinning::SkinnedMeshInverseBindposes>()
26            .register_asset_reflect::<Mesh>()
27            .register_type::<skinning::SkinnedMesh>()
28            .register_type::<Vec<Entity>>()
29            // 'Mesh' must be prepared after 'Image' as meshes rely on the morph target image being ready
30            .add_plugins(RenderAssetPlugin::<GpuMesh, GpuImage>::default());
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/// Describes the layout of the mesh vertices in GPU memory.
41///
42/// At most one copy of a mesh vertex buffer layout ever exists in GPU memory at
43/// once. Therefore, comparing these for equality requires only a single pointer
44/// comparison, and this type's [`PartialEq`] and [`Hash`] implementations take
45/// advantage of this. To that end, this type doesn't implement
46/// [`bevy_derive::Deref`] or [`bevy_derive::DerefMut`] in order to reduce the
47/// possibility of accidental deep comparisons, which would be needlessly
48/// expensive.
49#[derive(Clone, Debug)]
50pub struct MeshVertexBufferLayoutRef(pub Arc<MeshVertexBufferLayout>);
51
52/// Stores the single copy of each mesh vertex buffer layout.
53#[derive(Clone, Default, Resource)]
54pub struct MeshVertexBufferLayouts(HashSet<Arc<MeshVertexBufferLayout>>);
55
56impl MeshVertexBufferLayouts {
57    /// Inserts a new mesh vertex buffer layout in the store and returns a
58    /// reference to it, reusing the existing reference if this mesh vertex
59    /// buffer layout was already in the store.
60    pub fn insert(&mut self, layout: MeshVertexBufferLayout) -> MeshVertexBufferLayoutRef {
61        // Because the special `PartialEq` and `Hash` implementations that
62        // compare by pointer are on `MeshVertexBufferLayoutRef`, not on
63        // `Arc<MeshVertexBufferLayout>`, this compares the mesh vertex buffer
64        // structurally, not by pointer.
65        MeshVertexBufferLayoutRef(
66            self.0
67                .get_or_insert_with(&layout, |layout| Arc::new(layout.clone()))
68                .clone(),
69        )
70    }
71}
72
73impl PartialEq for MeshVertexBufferLayoutRef {
74    fn eq(&self, other: &Self) -> bool {
75        Arc::ptr_eq(&self.0, &other.0)
76    }
77}
78
79impl Eq for MeshVertexBufferLayoutRef {}
80
81impl Hash for MeshVertexBufferLayoutRef {
82    fn hash<H: Hasher>(&self, state: &mut H) {
83        // Hash the address of the underlying data, so two layouts that share the same
84        // `MeshVertexBufferLayout` will have the same hash.
85        (Arc::as_ptr(&self.0) as usize).hash(state);
86    }
87}