Skip to main content

bevy_mesh/primitives/dim3/
cuboid.rs

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