Skip to content

Commit bb51635

Browse files
authored
Add subdivisions to PlaneMeshBuilder (#13580)
# Objective - Plane subdivision was removed without providing an alternative ## Solution - Add subdivision to the PlaneMeshBuilder --- ## Migration Guide If you were using `Plane` `subdivisions`, you now need to use `Plane3d::default().mesh().subdivisions(10)` fixes #13258
1 parent 52ace67 commit bb51635

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

crates/bevy_render/src/mesh/primitives/dim3/plane.rs

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ use crate::{
1111
pub struct PlaneMeshBuilder {
1212
/// The [`Plane3d`] shape.
1313
pub plane: Plane3d,
14+
/// The number of subdivisions in the mesh.
15+
///
16+
/// 0 - is the original plane geometry, the 4 points in the XZ plane.
17+
///
18+
/// 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.
19+
///
20+
/// 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.
21+
///
22+
/// and so on...
23+
pub subdivisions: u32,
1424
}
1525

1626
impl PlaneMeshBuilder {
@@ -22,6 +32,7 @@ impl PlaneMeshBuilder {
2232
normal,
2333
half_size: size / 2.0,
2434
},
35+
subdivisions: 0,
2536
}
2637
}
2738

@@ -33,6 +44,7 @@ impl PlaneMeshBuilder {
3344
half_size: size / 2.0,
3445
..Default::default()
3546
},
47+
subdivisions: 0,
3648
}
3749
}
3850

@@ -45,6 +57,7 @@ impl PlaneMeshBuilder {
4557
half_size: Vec2::splat(length) / 2.0,
4658
..Default::default()
4759
},
60+
subdivisions: 0,
4861
}
4962
}
5063

@@ -65,27 +78,66 @@ impl PlaneMeshBuilder {
6578
self.plane.half_size = Vec2::new(width, height) / 2.0;
6679
self
6780
}
81+
82+
/// Sets the subdivisions of the plane mesh.
83+
///
84+
/// 0 - is the original plane geometry, the 4 points in the XZ plane.
85+
///
86+
/// 1 - is split by 1 line in the middle of the plane on both the X axis and the Z axis,
87+
/// resulting in a plane with 4 quads / 8 triangles.
88+
///
89+
/// 2 - is a plane split by 2 lines on both the X and Z axes, subdividing the plane into 3
90+
/// equal sections along each axis, resulting in a plane with 9 quads / 18 triangles.
91+
#[inline]
92+
pub fn subdivisions(mut self, subdivisions: u32) -> Self {
93+
self.subdivisions = subdivisions;
94+
self
95+
}
6896
}
6997

7098
impl MeshBuilder for PlaneMeshBuilder {
7199
fn build(&self) -> Mesh {
100+
let z_vertex_count = self.subdivisions + 2;
101+
let x_vertex_count = self.subdivisions + 2;
102+
let num_vertices = (z_vertex_count * x_vertex_count) as usize;
103+
let num_indices = ((z_vertex_count - 1) * (x_vertex_count - 1) * 6) as usize;
104+
105+
let mut positions: Vec<Vec3> = Vec::with_capacity(num_vertices);
106+
let mut normals: Vec<[f32; 3]> = Vec::with_capacity(num_vertices);
107+
let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(num_vertices);
108+
let mut indices: Vec<u32> = Vec::with_capacity(num_indices);
109+
72110
let rotation = Quat::from_rotation_arc(Vec3::Y, *self.plane.normal);
73-
let positions = vec![
74-
rotation * Vec3::new(self.plane.half_size.x, 0.0, -self.plane.half_size.y),
75-
rotation * Vec3::new(-self.plane.half_size.x, 0.0, -self.plane.half_size.y),
76-
rotation * Vec3::new(-self.plane.half_size.x, 0.0, self.plane.half_size.y),
77-
rotation * Vec3::new(self.plane.half_size.x, 0.0, self.plane.half_size.y),
78-
];
111+
let size = self.plane.half_size * 2.0;
79112

80-
let normals = vec![self.plane.normal.to_array(); 4];
81-
let uvs = vec![[1.0, 0.0], [0.0, 0.0], [0.0, 1.0], [1.0, 1.0]];
82-
let indices = Indices::U32(vec![0, 1, 2, 0, 2, 3]);
113+
for z in 0..z_vertex_count {
114+
for x in 0..x_vertex_count {
115+
let tx = x as f32 / (x_vertex_count - 1) as f32;
116+
let tz = z as f32 / (z_vertex_count - 1) as f32;
117+
let pos = rotation * Vec3::new((-0.5 + tx) * size.x, 0.0, (-0.5 + tz) * size.y);
118+
positions.push(pos);
119+
normals.push(self.plane.normal.to_array());
120+
uvs.push([tx, tz]);
121+
}
122+
}
123+
124+
for z in 0..z_vertex_count - 1 {
125+
for x in 0..x_vertex_count - 1 {
126+
let quad = z * x_vertex_count + x;
127+
indices.push(quad + x_vertex_count + 1);
128+
indices.push(quad + 1);
129+
indices.push(quad + x_vertex_count);
130+
indices.push(quad);
131+
indices.push(quad + x_vertex_count);
132+
indices.push(quad + 1);
133+
}
134+
}
83135

84136
Mesh::new(
85137
PrimitiveTopology::TriangleList,
86138
RenderAssetUsages::default(),
87139
)
88-
.with_inserted_indices(indices)
140+
.with_inserted_indices(Indices::U32(indices))
89141
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
90142
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
91143
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
@@ -96,7 +148,10 @@ impl Meshable for Plane3d {
96148
type Output = PlaneMeshBuilder;
97149

98150
fn mesh(&self) -> Self::Output {
99-
PlaneMeshBuilder { plane: *self }
151+
PlaneMeshBuilder {
152+
plane: *self,
153+
subdivisions: 0,
154+
}
100155
}
101156
}
102157

examples/3d/3d_shapes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ fn setup(
8686

8787
// ground plane
8888
commands.spawn(PbrBundle {
89-
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0)),
89+
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0).subdivisions(10)),
9090
material: materials.add(Color::from(SILVER)),
9191
..default()
9292
});

0 commit comments

Comments
 (0)