bevy_mesh/primitives/dim3/
cuboid.rs

1use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
2use bevy_asset::RenderAssetUsages;
3use bevy_math::{primitives::Cuboid, Vec3};
4use bevy_reflect::prelude::*;
5
6/// A builder used for creating a [`Mesh`] with a [`Cuboid`] shape.
7#[derive(Clone, Copy, Debug, Reflect)]
8#[reflect(Default, Debug, Clone)]
9pub struct CuboidMeshBuilder {
10    half_size: Vec3,
11}
12
13impl Default for CuboidMeshBuilder {
14    /// Returns the default [`CuboidMeshBuilder`] with a width, height, and depth of `1.0`.
15    fn default() -> Self {
16        Self {
17            half_size: Vec3::splat(0.5),
18        }
19    }
20}
21
22impl MeshBuilder for CuboidMeshBuilder {
23    fn build(&self) -> Mesh {
24        let min = -self.half_size;
25        let max = self.half_size;
26
27        // Suppose Y-up right hand, and camera look from +Z to -Z
28        let vertices = &[
29            // Front
30            ([min.x, min.y, max.z], [0.0, 0.0, 1.0], [0.0, 0.0]),
31            ([max.x, min.y, max.z], [0.0, 0.0, 1.0], [1.0, 0.0]),
32            ([max.x, max.y, max.z], [0.0, 0.0, 1.0], [1.0, 1.0]),
33            ([min.x, max.y, max.z], [0.0, 0.0, 1.0], [0.0, 1.0]),
34            // Back
35            ([min.x, max.y, min.z], [0.0, 0.0, -1.0], [1.0, 0.0]),
36            ([max.x, max.y, min.z], [0.0, 0.0, -1.0], [0.0, 0.0]),
37            ([max.x, min.y, min.z], [0.0, 0.0, -1.0], [0.0, 1.0]),
38            ([min.x, min.y, min.z], [0.0, 0.0, -1.0], [1.0, 1.0]),
39            // Right
40            ([max.x, min.y, min.z], [1.0, 0.0, 0.0], [0.0, 0.0]),
41            ([max.x, max.y, min.z], [1.0, 0.0, 0.0], [1.0, 0.0]),
42            ([max.x, max.y, max.z], [1.0, 0.0, 0.0], [1.0, 1.0]),
43            ([max.x, min.y, max.z], [1.0, 0.0, 0.0], [0.0, 1.0]),
44            // Left
45            ([min.x, min.y, max.z], [-1.0, 0.0, 0.0], [1.0, 0.0]),
46            ([min.x, max.y, max.z], [-1.0, 0.0, 0.0], [0.0, 0.0]),
47            ([min.x, max.y, min.z], [-1.0, 0.0, 0.0], [0.0, 1.0]),
48            ([min.x, min.y, min.z], [-1.0, 0.0, 0.0], [1.0, 1.0]),
49            // Top
50            ([max.x, max.y, min.z], [0.0, 1.0, 0.0], [1.0, 0.0]),
51            ([min.x, max.y, min.z], [0.0, 1.0, 0.0], [0.0, 0.0]),
52            ([min.x, max.y, max.z], [0.0, 1.0, 0.0], [0.0, 1.0]),
53            ([max.x, max.y, max.z], [0.0, 1.0, 0.0], [1.0, 1.0]),
54            // Bottom
55            ([max.x, min.y, max.z], [0.0, -1.0, 0.0], [0.0, 0.0]),
56            ([min.x, min.y, max.z], [0.0, -1.0, 0.0], [1.0, 0.0]),
57            ([min.x, min.y, min.z], [0.0, -1.0, 0.0], [1.0, 1.0]),
58            ([max.x, min.y, min.z], [0.0, -1.0, 0.0], [0.0, 1.0]),
59        ];
60
61        let positions: Vec<_> = vertices.iter().map(|(p, _, _)| *p).collect();
62        let normals: Vec<_> = vertices.iter().map(|(_, n, _)| *n).collect();
63        let uvs: Vec<_> = vertices.iter().map(|(_, _, uv)| *uv).collect();
64
65        let indices = Indices::U32(vec![
66            0, 1, 2, 2, 3, 0, // front
67            4, 5, 6, 6, 7, 4, // back
68            8, 9, 10, 10, 11, 8, // right
69            12, 13, 14, 14, 15, 12, // left
70            16, 17, 18, 18, 19, 16, // top
71            20, 21, 22, 22, 23, 20, // bottom
72        ]);
73
74        Mesh::new(
75            PrimitiveTopology::TriangleList,
76            RenderAssetUsages::default(),
77        )
78        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
79        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
80        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
81        .with_inserted_indices(indices)
82    }
83}
84
85impl Meshable for Cuboid {
86    type Output = CuboidMeshBuilder;
87
88    fn mesh(&self) -> Self::Output {
89        CuboidMeshBuilder {
90            half_size: self.half_size,
91        }
92    }
93}
94
95impl From<Cuboid> for Mesh {
96    fn from(cuboid: Cuboid) -> Self {
97        cuboid.mesh().build()
98    }
99}