Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_mesh/src/primitives/dim3/plane.rs
6598 views
1
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
2
use bevy_asset::RenderAssetUsages;
3
use bevy_math::{primitives::Plane3d, Dir3, Quat, Vec2, Vec3};
4
use bevy_reflect::prelude::*;
5
6
/// A builder used for creating a [`Mesh`] with a [`Plane3d`] shape.
7
#[derive(Clone, Copy, Debug, Default, Reflect)]
8
#[reflect(Default, Debug, Clone)]
9
pub struct PlaneMeshBuilder {
10
/// The [`Plane3d`] shape.
11
pub plane: Plane3d,
12
/// The number of subdivisions in the mesh.
13
///
14
/// 0 - is the original plane geometry, the 4 points in the XZ plane.
15
///
16
/// 1 - is split by 1 line in the middle of the plane on both the X axis and the Z axis, resulting in a plane with 4 quads / 8 triangles.
17
///
18
/// 2 - is a plane split by 2 lines on both the X and Z axes, subdividing the plane into 3 equal sections along each axis, resulting in a plane with 9 quads / 18 triangles.
19
///
20
/// and so on...
21
pub subdivisions: u32,
22
}
23
24
impl PlaneMeshBuilder {
25
/// Creates a new [`PlaneMeshBuilder`] from a given normal and size.
26
#[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
/// Creates a new [`PlaneMeshBuilder`] from the given size, with the normal pointing upwards.
38
#[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
/// Creates a new [`PlaneMeshBuilder`] from the given length, with the normal pointing upwards,
50
/// and the resulting [`PlaneMeshBuilder`] being a square.
51
#[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
/// Sets the normal of the plane, aka the direction the plane is facing.
63
#[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
/// Sets the size of the plane mesh.
74
#[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
/// Sets the subdivisions of the plane mesh.
81
///
82
/// 0 - is the original plane geometry, the 4 points in the XZ plane.
83
///
84
/// 1 - is split by 1 line in the middle of the plane on both the X axis and the Z axis,
85
/// resulting in a plane with 4 quads / 8 triangles.
86
///
87
/// 2 - is a plane split by 2 lines on both the X and Z axes, subdividing the plane into 3
88
/// equal sections along each axis, resulting in a plane with 9 quads / 18 triangles.
89
#[inline]
90
pub fn subdivisions(mut self, subdivisions: u32) -> Self {
91
self.subdivisions = subdivisions;
92
self
93
}
94
}
95
96
impl 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
145
impl 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
156
impl From<Plane3d> for Mesh {
157
fn from(plane: Plane3d) -> Self {
158
plane.mesh().build()
159
}
160
}
161
162