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