Path: blob/main/crates/bevy_mesh/src/primitives/dim3/plane.rs
6598 views
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};1use bevy_asset::RenderAssetUsages;2use bevy_math::{primitives::Plane3d, Dir3, Quat, Vec2, Vec3};3use bevy_reflect::prelude::*;45/// A builder used for creating a [`Mesh`] with a [`Plane3d`] shape.6#[derive(Clone, Copy, Debug, Default, Reflect)]7#[reflect(Default, Debug, Clone)]8pub struct PlaneMeshBuilder {9/// The [`Plane3d`] shape.10pub plane: Plane3d,11/// The number of subdivisions in the mesh.12///13/// 0 - is the original plane geometry, the 4 points in the XZ plane.14///15/// 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.16///17/// 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.18///19/// and so on...20pub subdivisions: u32,21}2223impl PlaneMeshBuilder {24/// Creates a new [`PlaneMeshBuilder`] from a given normal and size.25#[inline]26pub fn new(normal: Dir3, size: Vec2) -> Self {27Self {28plane: Plane3d {29normal,30half_size: size / 2.0,31},32subdivisions: 0,33}34}3536/// Creates a new [`PlaneMeshBuilder`] from the given size, with the normal pointing upwards.37#[inline]38pub fn from_size(size: Vec2) -> Self {39Self {40plane: Plane3d {41half_size: size / 2.0,42..Default::default()43},44subdivisions: 0,45}46}4748/// Creates a new [`PlaneMeshBuilder`] from the given length, with the normal pointing upwards,49/// and the resulting [`PlaneMeshBuilder`] being a square.50#[inline]51pub fn from_length(length: f32) -> Self {52Self {53plane: Plane3d {54half_size: Vec2::splat(length) / 2.0,55..Default::default()56},57subdivisions: 0,58}59}6061/// Sets the normal of the plane, aka the direction the plane is facing.62#[inline]63#[doc(alias = "facing")]64pub fn normal(mut self, normal: Dir3) -> Self {65self.plane = Plane3d {66normal,67..self.plane68};69self70}7172/// Sets the size of the plane mesh.73#[inline]74pub fn size(mut self, width: f32, height: f32) -> Self {75self.plane.half_size = Vec2::new(width, height) / 2.0;76self77}7879/// Sets the subdivisions of the plane mesh.80///81/// 0 - is the original plane geometry, the 4 points in the XZ plane.82///83/// 1 - is split by 1 line in the middle of the plane on both the X axis and the Z axis,84/// resulting in a plane with 4 quads / 8 triangles.85///86/// 2 - is a plane split by 2 lines on both the X and Z axes, subdividing the plane into 387/// equal sections along each axis, resulting in a plane with 9 quads / 18 triangles.88#[inline]89pub fn subdivisions(mut self, subdivisions: u32) -> Self {90self.subdivisions = subdivisions;91self92}93}9495impl MeshBuilder for PlaneMeshBuilder {96fn build(&self) -> Mesh {97let z_vertex_count = self.subdivisions + 2;98let x_vertex_count = self.subdivisions + 2;99let num_vertices = (z_vertex_count * x_vertex_count) as usize;100let num_indices = ((z_vertex_count - 1) * (x_vertex_count - 1) * 6) as usize;101102let mut positions: Vec<Vec3> = Vec::with_capacity(num_vertices);103let mut normals: Vec<[f32; 3]> = Vec::with_capacity(num_vertices);104let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(num_vertices);105let mut indices: Vec<u32> = Vec::with_capacity(num_indices);106107let rotation = Quat::from_rotation_arc(Vec3::Y, *self.plane.normal);108let size = self.plane.half_size * 2.0;109110for z in 0..z_vertex_count {111for x in 0..x_vertex_count {112let tx = x as f32 / (x_vertex_count - 1) as f32;113let tz = z as f32 / (z_vertex_count - 1) as f32;114let pos = rotation * Vec3::new((-0.5 + tx) * size.x, 0.0, (-0.5 + tz) * size.y);115positions.push(pos);116normals.push(self.plane.normal.to_array());117uvs.push([tx, tz]);118}119}120121for z in 0..z_vertex_count - 1 {122for x in 0..x_vertex_count - 1 {123let quad = z * x_vertex_count + x;124indices.push(quad + x_vertex_count + 1);125indices.push(quad + 1);126indices.push(quad + x_vertex_count);127indices.push(quad);128indices.push(quad + x_vertex_count);129indices.push(quad + 1);130}131}132133Mesh::new(134PrimitiveTopology::TriangleList,135RenderAssetUsages::default(),136)137.with_inserted_indices(Indices::U32(indices))138.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)139.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)140.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)141}142}143144impl Meshable for Plane3d {145type Output = PlaneMeshBuilder;146147fn mesh(&self) -> Self::Output {148PlaneMeshBuilder {149plane: *self,150subdivisions: 0,151}152}153}154155impl From<Plane3d> for Mesh {156fn from(plane: Plane3d) -> Self {157plane.mesh().build()158}159}160161162