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