Commit Graph

8 Commits

Author SHA1 Message Date
Lynn
03f4cc5dde
Extrusion (#13270)
# Objective

- Adds a basic `Extrusion<T: Primitive2d>` shape, suggestion of #10572 

## Solution

- Adds `Measured2d` and `Measured3d` traits for getting the
perimeter/area or area/volume of shapes. This allows implementing
`.volume()` and `.area()` for all extrusions `Extrusion<T: Primitive2d +
Measured2d>` within `bevy_math`
- All existing perimeter, area and volume implementations for primitves
have been moved into implementations of `Measured2d` and `Measured3d`
- Shapes should be extruded along the Z-axis since an extrusion of depth
`0.` should be equivalent in everything but name to the base shape

## Caviats

- I am not sure about the naming. `Extrusion<T>` could also be
`Prism<T>` and the `MeasuredNd` could also be something like
`MeasuredPrimitiveNd`. If you have any other suggestions, please fell
free to share them :)

## Future work

This PR adds a basic `Extrusion` shape and does not implement a lot of
things you might want it to. Some of the future possibilities include:
- [ ] bounding for extrusions
- [ ] making extrusions work with gizmos
- [ ] meshing

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-05-07 14:41:55 +00:00
nullicorn
f496d2a3c3
Additional doc aliases for WindingOrder in bevy_math (#13065)
# Objective

Adds a few extra `#[doc(alias)]` entries to the
`bevy_math::primitives::WindingOrder` enum and its variants to improve
searchability.

## Solution

- Add "Orientation" for `WindingOrder` itself
- Add "AntiClockwise" for `CounterClockwise` variant
- Add "Collinear" for `Invalid` variant

These alternate terms seem to be quite common, especially in the
contexts of rendering and collision-detection.

Signed-off-by: Nullicorn <git@nullicorn.me>
2024-04-22 21:50:27 +00:00
Joona Aalto
9bd6cc0a5e
Add Direction3dA and move direction types out of primitives (#12018)
# Objective

Split up from #12017, add an aligned version of `Direction3d` for SIMD,
and move direction types out of `primitives`.

## Solution

Add `Direction3dA` and move direction types into a new `direction`
module.

---

## Migration Guide

The `Direction2d`, `Direction3d`, and `InvalidDirectionError` types have
been moved out of `bevy::math::primitives`.

Before:

```rust
use bevy::math::primitives::Direction3d;
```

After:

```rust
use bevy::math::Direction3d;
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-02-26 13:57:49 +00:00
NiseVoid
755917fe4b
Derive PartialEq, Serialize, Deserialize and Reflect on primitives (#11514)
# Objective

- Implement common traits on primitives

## Solution

- Derive PartialEq on types that were missing it.
- Derive Copy on small types that were missing it.
- Derive Serialize/Deserialize if the feature on bevy_math is enabled.
- Add a lot of cursed stuff to the bevy_reflect `impls` module.
2024-01-28 14:55:30 +00:00
Joona Aalto
bcbb7bb9dd
Add new_and_length method to Direction2d and Direction3d (#11172)
# Objective

When creating a normalized direction from a vector, it can be useful to
get both the direction *and* the original length of the vector.

This came up when I was recreating some Parry APIs using bevy_math, and
doing it manually is quite painful. Nalgebra calls this method
[`Unit::try_new_and_get`](https://docs.rs/nalgebra/latest/nalgebra/base/struct.Unit.html#method.try_new_and_get).

## Solution

Add a `new_and_length` method to `Direction2d` and `Direction3d`.

Usage:

```rust
if let Ok((direction, length)) = Direction2d::new_and_length(Vec2::X * 10.0) {
    assert_eq!(direction, Vec2::X);
    assert_eq!(length, 10.0);
}
```

I'm open to different names, couldn't come up with a perfectly clear one
that isn't too long. My reasoning with the current name is that it's
like using `new` and calling `length` on the original vector.
2024-01-08 22:36:56 +00:00
Joona Aalto
f683b802f1
Impl TryFrom vector for directions and add InvalidDirectionError (#10884)
# Objective

Implement `TryFrom<Vec2>`/`TryFrom<Vec3>` for direction primitives as
considered in #10857.

## Solution

Implement `TryFrom` for the direction primitives.

These are all equivalent:

```rust
let dir2d = Direction2d::try_from(Vec2::new(0.5, 0.5)).unwrap();
let dir2d = Vec2::new(0.5, 0.5).try_into().unwrap(); // (assumes that the type is inferred)
let dir2d = Direction2d::new(Vec2::new(0.5, 0.5)).unwrap();
```

For error cases, an `Err(InvalidDirectionError)` is returned. It
contains the type of failure:

```rust
/// An error indicating that a direction is invalid.
#[derive(Debug, PartialEq)]
pub enum InvalidDirectionError {
    /// The length of the direction vector is zero or very close to zero.
    Zero,
    /// The length of the direction vector is `std::f32::INFINITY`.
    Infinite,
    /// The length of the direction vector is `NaN`.
    NaN,
}
```
2023-12-06 00:05:37 +00:00
Joona Aalto
e1c8d60f91
Add winding order for Triangle2d (#10620)
# Objective

This PR adds some helpers for `Triangle2d` to work with its winding
order. This could also be extended to polygons (and `Triangle3d` once
it's added).

## Solution

- Add `WindingOrder` enum with `Clockwise`, `Counterclockwise` and
`Invalid` variants
- `Invalid` is for cases where the winding order can not be reliably
computed, i.e. the points lie on a single line and the area is zero
- Add `Triangle2d::winding_order` method that uses a signed surface area
to determine the winding order
- Add `Triangle2d::reverse` method that reverses the winding order by
swapping the second and third vertices

The API looks like this:

```rust
let mut triangle = Triangle2d::new(
    Vec2::new(0.0, 2.0),
    Vec2::new(-0.5, -1.2),
    Vec2::new(-1.0, -1.0),
);
assert_eq!(triangle.winding_order(), WindingOrder::Clockwise);

// Reverse winding order
triangle.reverse();
assert_eq!(triangle.winding_order(), WindingOrder::Counterclockwise);
```

I also added tests to make sure the methods work correctly. For now,
they live in the same file as the primitives.

## Open questions

- Should it be `Counterclockwise` or `CounterClockwise`? The first one
is more correct but perhaps a bit less readable. Counter-clockwise is
also a valid spelling, but it seems to be a lot less common than
counterclockwise.
- Is `WindingOrder::Invalid` a good name? Parry uses
`TriangleOrientation::Degenerate`, but I'm not a huge fan, at least as a
non-native English speaker. Any better suggestions?
- Is `WindingOrder` fine in `bevy_math::primitives`? It's not specific
to a dimension, so I put it there for now.
2023-11-20 09:47:05 +00:00
NiseVoid
01b9ddd92c
Define a basic set of Primitives (#10466)
# Objective

- Implement a subset of
https://github.com/bevyengine/rfcs/blob/main/rfcs/12-primitive-shapes.md#feature-name-primitive-shapes

## Solution

- Define a very basic set of primitives in bevy_math
- Assume a 0,0,0 origin for most shapes
- Use radius and half extents to avoid unnecessary computational
overhead wherever they get used
- Provide both Boxed and const generics variants for shapes with
variable sizes
- Boxed is useful if a 3rd party crate wants to use something like
enum-dispatch for all supported primitives
- Const generics is useful when just working on a single primitive, as
it causes no allocs

#### Some discrepancies from the RFC:

- Box was changed to Cuboid, because Box is already used for an alloc
type
- Skipped Cone because it's unclear where the origin should be for
different uses
- Skipped Wedge because it's too niche for an initial PR (we also don't
implement Torus, Pyramid or a Death Star (there's an SDF for that!))
- Skipped Frustum because while it would be a useful math type, it's not
really a common primitive
- Skipped Triangle3d and Quad3d because those are just rotated 2D shapes

## Future steps

- Add more primitives
- Add helper methods to make primitives easier to construct (especially
when half extents are involved)
- Add methods to calculate AABBs for primitives (useful for physics, BVH
construction, for the mesh AABBs, etc)
- Add wrappers for common and cheap operations, like extruding 2D shapes
and translating them
- Use the primitives to generate meshes
- Provide signed distance functions and gradients for primitives (maybe)

---

## Changelog

- Added a collection of primitives to the bevy_math crate

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2023-11-15 16:51:03 +00:00