bevy_mesh/primitives/dim3/
plane.rs1use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
2use bevy_asset::RenderAssetUsages;
3use bevy_math::{primitives::Plane3d, Dir3, Quat, Vec2, Vec3};
4use bevy_reflect::prelude::*;
5
6#[derive(Clone, Copy, Debug, Default, Reflect)]
8#[reflect(Default, Debug, Clone)]
9pub struct PlaneMeshBuilder {
10 pub plane: Plane3d,
12 pub subdivisions_x: u32,
22
23 pub subdivisions_z: u32,
33}
34
35impl PlaneMeshBuilder {
36 #[inline]
38 pub fn new(normal: Dir3, size: Vec2) -> Self {
39 Self {
40 plane: Plane3d {
41 normal,
42 half_size: size / 2.0,
43 },
44 subdivisions_x: 0,
45 subdivisions_z: 0,
46 }
47 }
48
49 #[inline]
51 pub fn from_size(size: Vec2) -> Self {
52 Self {
53 plane: Plane3d {
54 half_size: size / 2.0,
55 ..Default::default()
56 },
57 subdivisions_x: 0,
58 subdivisions_z: 0,
59 }
60 }
61
62 #[inline]
65 pub fn from_length(length: f32) -> Self {
66 Self {
67 plane: Plane3d {
68 half_size: Vec2::splat(length) / 2.0,
69 ..Default::default()
70 },
71 subdivisions_x: 0,
72 subdivisions_z: 0,
73 }
74 }
75
76 #[inline]
78 #[doc(alias = "facing")]
79 pub fn normal(mut self, normal: Dir3) -> Self {
80 self.plane = Plane3d {
81 normal,
82 ..self.plane
83 };
84 self
85 }
86
87 #[inline]
89 pub fn size(mut self, width: f32, height: f32) -> Self {
90 self.plane.half_size = Vec2::new(width, height) / 2.0;
91 self
92 }
93
94 #[inline]
104 pub fn subdivisions(mut self, subdivisions: u32) -> Self {
105 self.subdivisions_x = subdivisions;
106 self.subdivisions_z = subdivisions;
107 self
108 }
109
110 #[inline]
111 pub fn subdivisions_x(mut self, subdivisions: u32) -> Self {
121 self.subdivisions_x = subdivisions;
122 self
123 }
124
125 #[inline]
126 pub fn subdivisions_z(mut self, subdivisions: u32) -> Self {
136 self.subdivisions_z = subdivisions;
137 self
138 }
139}
140
141impl MeshBuilder for PlaneMeshBuilder {
142 fn build(&self) -> Mesh {
143 let z_vertex_count = self.subdivisions_z + 2;
144 let x_vertex_count = self.subdivisions_x + 2;
145 let num_vertices = (z_vertex_count * x_vertex_count) as usize;
146 let num_indices = ((z_vertex_count - 1) * (x_vertex_count - 1) * 6) as usize;
147
148 let mut positions: Vec<Vec3> = Vec::with_capacity(num_vertices);
149 let mut normals: Vec<[f32; 3]> = Vec::with_capacity(num_vertices);
150 let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(num_vertices);
151 let mut indices: Vec<u32> = Vec::with_capacity(num_indices);
152
153 let rotation = Quat::from_rotation_arc(Vec3::Y, *self.plane.normal);
154 let size = self.plane.half_size * 2.0;
155
156 for z in 0..z_vertex_count {
157 for x in 0..x_vertex_count {
158 let tx = x as f32 / (x_vertex_count - 1) as f32;
159 let tz = z as f32 / (z_vertex_count - 1) as f32;
160 let pos = rotation * Vec3::new((-0.5 + tx) * size.x, 0.0, (-0.5 + tz) * size.y);
161 positions.push(pos);
162 normals.push(self.plane.normal.to_array());
163 uvs.push([tx, tz]);
164 }
165 }
166
167 for z in 0..z_vertex_count - 1 {
168 for x in 0..x_vertex_count - 1 {
169 let quad = z * x_vertex_count + x;
170 indices.push(quad + x_vertex_count + 1);
171 indices.push(quad + 1);
172 indices.push(quad + x_vertex_count);
173 indices.push(quad);
174 indices.push(quad + x_vertex_count);
175 indices.push(quad + 1);
176 }
177 }
178
179 Mesh::new(
180 PrimitiveTopology::TriangleList,
181 RenderAssetUsages::default(),
182 )
183 .with_inserted_indices(Indices::U32(indices))
184 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
185 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
186 .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
187 }
188}
189
190impl Meshable for Plane3d {
191 type Output = PlaneMeshBuilder;
192
193 fn mesh(&self) -> Self::Output {
194 PlaneMeshBuilder {
195 plane: *self,
196 subdivisions_x: 0,
197 subdivisions_z: 0,
198 }
199 }
200}
201
202impl From<Plane3d> for Mesh {
203 fn from(plane: Plane3d) -> Self {
204 plane.mesh().build()
205 }
206}