Skip to content

Commit

Permalink
adding the rect3d primitive
Browse files Browse the repository at this point in the history
  • Loading branch information
andristarr committed Mar 13, 2024
1 parent 309745c commit a2db276
Show file tree
Hide file tree
Showing 37 changed files with 235 additions and 201 deletions.
40 changes: 20 additions & 20 deletions crates/bevy_gizmos/src/primitives/dim3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use std::f32::consts::TAU;

use bevy_color::Color;
use bevy_math::primitives::{
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d,
Polyline3d, Primitive3d, Segment3d, Sphere, Torus,
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Polyline3d,
Primitive3d, Rect3d, Segment3d, Sphere, Torus,
};
use bevy_math::{Dir3, Quat, Vec3};

Expand Down Expand Up @@ -132,38 +132,38 @@ impl<T: GizmoConfigGroup> Drop for SphereBuilder<'_, '_, '_, T> {
}
}

// plane 3d
// rect 3d

/// Builder for configuring the drawing options of [`Sphere`].
pub struct Plane3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
/// Builder for configuring the drawing options of [`Rect3d`].
pub struct Rect3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
gizmos: &'a mut Gizmos<'w, 's, T>,

// direction of the normal orthogonal to the plane
// direction of the normal orthogonal to the rectangle
normal: Dir3,

// Rotation of the sphere around the origin in 3D space
// Rotation of the rectangle around the origin in 3D space
rotation: Quat,
// Center position of the sphere in 3D space
// Center position of the rectangle in 3D space
position: Vec3,
// Color of the sphere
// Color of the rectangle
color: Color,

// Number of axis to hint the plane
// Number of axis to hint the rectangle
axis_count: usize,
// Number of segments used to hint the plane
// Number of segments used to hint the rectangle
segment_count: usize,
// Length of segments used to hint the plane
// Length of segments used to hint the rectangle
segment_length: f32,
}

impl<T: GizmoConfigGroup> Plane3dBuilder<'_, '_, '_, T> {
/// Set the number of segments used to hint the plane.
impl<T: GizmoConfigGroup> Rect3dBuilder<'_, '_, '_, T> {
/// Set the number of segments used to hint the rectangle.
pub fn segment_count(mut self, count: usize) -> Self {
self.segment_count = count;
self
}

/// Set the length of segments used to hint the plane.
/// Set the length of segments used to hint the rectangle.
pub fn segment_length(mut self, length: f32) -> Self {
self.segment_length = length;
self
Expand All @@ -176,17 +176,17 @@ impl<T: GizmoConfigGroup> Plane3dBuilder<'_, '_, '_, T> {
}
}

impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d<Plane3d> for Gizmos<'w, 's, T> {
type Output<'a> = Plane3dBuilder<'a, 'w, 's, T> where Self: 'a;
impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d<Rect3d> for Gizmos<'w, 's, T> {
type Output<'a> = Rect3dBuilder<'a, 'w, 's, T> where Self: 'a;

fn primitive_3d(
&mut self,
primitive: Plane3d,
primitive: Rect3d,
position: Vec3,
rotation: Quat,
color: Color,
) -> Self::Output<'_> {
Plane3dBuilder {
Rect3dBuilder {
gizmos: self,
normal: primitive.normal,
rotation,
Expand All @@ -199,7 +199,7 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d<Plane3d> for Gizmos<'w, 's, T
}
}

impl<T: GizmoConfigGroup> Drop for Plane3dBuilder<'_, '_, '_, T> {
impl<T: GizmoConfigGroup> Drop for Rect3dBuilder<'_, '_, '_, T> {
fn drop(&mut self) {
if !self.gizmos.enabled {
return;
Expand Down
38 changes: 37 additions & 1 deletion crates/bevy_math/src/primitives/dim3.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::f32::consts::{FRAC_PI_3, PI};

use super::{Circle, Primitive3d};
use crate::{Dir3, Vec3};
use crate::{Dir3, Vec2, Vec3};

/// A sphere primitive
#[derive(Clone, Copy, Debug, PartialEq)]
Expand Down Expand Up @@ -64,6 +64,42 @@ impl Sphere {
}
}

/// A bounded rectangle in 3D space. It forms a surface starting from the origin with a defined height and width.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct Rect3d {
/// The normal of the rectangle. The rectangle will be placed perpendicular to this direction
pub normal: Dir3,
/// Half of the width and height of the rectangle
pub half_size: Vec2,
}
impl Primitive3d for Rect3d {}

impl Default for Rect3d {
/// Returns the default [`Rect3d`] with a normal pointing in the `+Y` direction, width and height of `1.0`.
fn default() -> Self {
Self {
normal: Dir3::Y,
half_size: Vec2::splat(0.5),
}
}
}

impl Rect3d {
/// Create a new `Rect3d` from a normal and a half size
///
/// # Panics
///
/// Panics if the given `normal` is zero (or very close to zero), or non-finite.
#[inline(always)]
pub fn new(normal: Vec3, half_size: Vec2) -> Self {
Self {
normal: Dir3::new(normal).expect("normal must be nonzero and finite"),
half_size,
}
}
}

/// An unbounded plane in 3D space. It forms a separating surface through the origin,
/// stretching infinitely far
#[derive(Clone, Copy, Debug, PartialEq)]
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/mesh/primitives/dim3/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
mod capsule;
mod cuboid;
mod cylinder;
mod plane;
mod rect;
mod sphere;
mod torus;

pub use capsule::*;
pub use cylinder::*;
pub use plane::*;
pub use rect::*;
pub use sphere::*;
pub use torus::*;
117 changes: 0 additions & 117 deletions crates/bevy_render/src/mesh/primitives/dim3/plane.rs

This file was deleted.

112 changes: 112 additions & 0 deletions crates/bevy_render/src/mesh/primitives/dim3/rect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use bevy_math::{primitives::Rect3d, Dir3, Quat, Vec2, Vec3};
use wgpu::PrimitiveTopology;

use crate::{
mesh::{Indices, Mesh, Meshable},
render_asset::RenderAssetUsages,
};

/// A builder used for creating a [`Mesh`] with a [`Rect3d`] shape.
#[derive(Clone, Copy, Debug, Default)]
pub struct RectMeshBuilder {
/// The [`Rect3d`] shape.
pub rect: Rect3d,
}

impl RectMeshBuilder {
/// Creates a new [`RectMeshBuilder`] from a given normal and size.
#[inline]
pub fn new(normal: Dir3, size: Vec2) -> Self {
Self {
rect: Rect3d {
normal,
half_size: size / 2.0,
},
}
}

/// Creates a new [`RectMeshBuilder`] from the given size, with the normal pointing upwards.
#[inline]
pub fn from_size(size: Vec2) -> Self {
Self {
rect: Rect3d {
half_size: size / 2.0,
..Default::default()
},
}
}

/// Creates a new [`RectMeshBuilder`] from the given length, with the normal pointing upwards,
/// and the resulting [`RectMeshBuilder`] being a square.
#[inline]
pub fn from_length(length: f32) -> Self {
Self {
rect: Rect3d {
half_size: Vec2::splat(length) / 2.0,
..Default::default()
},
}
}

/// Sets the normal of the rectangle, aka the direction the rectangle is facing.
#[inline]
#[doc(alias = "facing")]
pub fn normal(mut self, normal: Dir3) -> Self {
self.rect = Rect3d {
normal,
..self.rect
};
self
}

/// Sets the size of the rectangle mesh.
#[inline]
pub fn size(mut self, width: f32, height: f32) -> Self {
self.rect.half_size = Vec2::new(width, height) / 2.0;
self
}

/// Builds a [`Mesh`] based on the configuration in `self`.
pub fn build(&self) -> Mesh {
let rotation = Quat::from_rotation_arc(Vec3::Y, *self.rect.normal);
let positions = vec![
rotation * Vec3::new(self.rect.half_size.x, 0.0, -self.rect.half_size.y),
rotation * Vec3::new(-self.rect.half_size.x, 0.0, -self.rect.half_size.y),
rotation * Vec3::new(-self.rect.half_size.x, 0.0, self.rect.half_size.y),
rotation * Vec3::new(self.rect.half_size.x, 0.0, self.rect.half_size.y),
];

let normals = vec![self.rect.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 Rect3d {
type Output = RectMeshBuilder;

fn mesh(&self) -> Self::Output {
RectMeshBuilder { rect: *self }
}
}

impl From<Rect3d> for Mesh {
fn from(rect: Rect3d) -> Self {
rect.mesh().build()
}
}

impl From<RectMeshBuilder> for Mesh {
fn from(rect: RectMeshBuilder) -> Self {
rect.build()
}
}
Loading

0 comments on commit a2db276

Please sign in to comment.