use bevy_math::{
primitives::{Direction3d, Plane3d},
Quat, Vec2, Vec3,
};
use wgpu::PrimitiveTopology;
use crate::{
mesh::{Indices, Mesh, Meshable},
render_asset::RenderAssetUsages,
};
#[derive(Clone, Copy, Debug)]
pub struct PlaneMeshBuilder {
pub plane: Plane3d,
pub half_size: Vec2,
}
impl Default for PlaneMeshBuilder {
fn default() -> Self {
Self {
plane: Plane3d::default(),
half_size: Vec2::ONE,
}
}
}
impl PlaneMeshBuilder {
#[inline]
pub fn new(normal: Direction3d, size: Vec2) -> Self {
Self {
plane: Plane3d { normal },
half_size: size / 2.0,
}
}
#[inline]
pub fn from_size(size: Vec2) -> Self {
Self {
half_size: size / 2.0,
..Default::default()
}
}
#[inline]
#[doc(alias = "facing")]
pub fn normal(mut self, normal: Direction3d) -> Self {
self.plane = Plane3d { normal };
self
}
#[inline]
pub fn size(mut self, width: f32, height: f32) -> Self {
self.half_size = Vec2::new(width, height) / 2.0;
self
}
pub fn build(&self) -> Mesh {
let rotation = Quat::from_rotation_arc(Vec3::Y, *self.plane.normal);
let positions = vec![
rotation * Vec3::new(self.half_size.x, 0.0, -self.half_size.y),
rotation * Vec3::new(-self.half_size.x, 0.0, -self.half_size.y),
rotation * Vec3::new(-self.half_size.x, 0.0, self.half_size.y),
rotation * Vec3::new(self.half_size.x, 0.0, self.half_size.y),
];
let normals = vec![self.plane.normal.to_array(); 4];
let uvs = vec![[1.0, 0.0], [0.0, 0.0], [0.0, 1.0], [1.0, 1.0]];
let indices = Indices::U32(vec![0, 1, 2, 0, 2, 3]);
Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetUsages::default(),
)
.with_inserted_indices(indices)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
}
}
impl Meshable for Plane3d {
type Output = PlaneMeshBuilder;
fn mesh(&self) -> Self::Output {
PlaneMeshBuilder {
plane: *self,
..Default::default()
}
}
}
impl From<Plane3d> for Mesh {
fn from(plane: Plane3d) -> Self {
plane.mesh().build()
}
}
impl From<PlaneMeshBuilder> for Mesh {
fn from(plane: PlaneMeshBuilder) -> Self {
plane.build()
}
}