bevy_mesh/primitives/dim3/
plane.rs1use crate::{Indices, Mesh, MeshBuilder, Meshable};
2use bevy_asset::RenderAssetUsages;
3use bevy_math::{primitives::Plane3d, Dir3, Quat, Vec2, Vec3};
4use wgpu::PrimitiveTopology;
5
6#[derive(Clone, Copy, Debug, Default)]
8pub struct PlaneMeshBuilder {
9 pub plane: Plane3d,
11 pub subdivisions: u32,
21}
22
23impl PlaneMeshBuilder {
24 #[inline]
26 pub fn new(normal: Dir3, size: Vec2) -> Self {
27 Self {
28 plane: Plane3d {
29 normal,
30 half_size: size / 2.0,
31 },
32 subdivisions: 0,
33 }
34 }
35
36 #[inline]
38 pub fn from_size(size: Vec2) -> Self {
39 Self {
40 plane: Plane3d {
41 half_size: size / 2.0,
42 ..Default::default()
43 },
44 subdivisions: 0,
45 }
46 }
47
48 #[inline]
51 pub fn from_length(length: f32) -> Self {
52 Self {
53 plane: Plane3d {
54 half_size: Vec2::splat(length) / 2.0,
55 ..Default::default()
56 },
57 subdivisions: 0,
58 }
59 }
60
61 #[inline]
63 #[doc(alias = "facing")]
64 pub fn normal(mut self, normal: Dir3) -> Self {
65 self.plane = Plane3d {
66 normal,
67 ..self.plane
68 };
69 self
70 }
71
72 #[inline]
74 pub fn size(mut self, width: f32, height: f32) -> Self {
75 self.plane.half_size = Vec2::new(width, height) / 2.0;
76 self
77 }
78
79 #[inline]
89 pub fn subdivisions(mut self, subdivisions: u32) -> Self {
90 self.subdivisions = subdivisions;
91 self
92 }
93}
94
95impl MeshBuilder for PlaneMeshBuilder {
96 fn build(&self) -> Mesh {
97 let z_vertex_count = self.subdivisions + 2;
98 let x_vertex_count = self.subdivisions + 2;
99 let num_vertices = (z_vertex_count * x_vertex_count) as usize;
100 let num_indices = ((z_vertex_count - 1) * (x_vertex_count - 1) * 6) as usize;
101
102 let mut positions: Vec<Vec3> = Vec::with_capacity(num_vertices);
103 let mut normals: Vec<[f32; 3]> = Vec::with_capacity(num_vertices);
104 let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(num_vertices);
105 let mut indices: Vec<u32> = Vec::with_capacity(num_indices);
106
107 let rotation = Quat::from_rotation_arc(Vec3::Y, *self.plane.normal);
108 let size = self.plane.half_size * 2.0;
109
110 for z in 0..z_vertex_count {
111 for x in 0..x_vertex_count {
112 let tx = x as f32 / (x_vertex_count - 1) as f32;
113 let tz = z as f32 / (z_vertex_count - 1) as f32;
114 let pos = rotation * Vec3::new((-0.5 + tx) * size.x, 0.0, (-0.5 + tz) * size.y);
115 positions.push(pos);
116 normals.push(self.plane.normal.to_array());
117 uvs.push([tx, tz]);
118 }
119 }
120
121 for z in 0..z_vertex_count - 1 {
122 for x in 0..x_vertex_count - 1 {
123 let quad = z * x_vertex_count + x;
124 indices.push(quad + x_vertex_count + 1);
125 indices.push(quad + 1);
126 indices.push(quad + x_vertex_count);
127 indices.push(quad);
128 indices.push(quad + x_vertex_count);
129 indices.push(quad + 1);
130 }
131 }
132
133 Mesh::new(
134 PrimitiveTopology::TriangleList,
135 RenderAssetUsages::default(),
136 )
137 .with_inserted_indices(Indices::U32(indices))
138 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
139 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
140 .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
141 }
142}
143
144impl Meshable for Plane3d {
145 type Output = PlaneMeshBuilder;
146
147 fn mesh(&self) -> Self::Output {
148 PlaneMeshBuilder {
149 plane: *self,
150 subdivisions: 0,
151 }
152 }
153}
154
155impl From<Plane3d> for Mesh {
156 fn from(plane: Plane3d) -> Self {
157 plane.mesh().build()
158 }
159}