Skip to content

Commit bc99e5b

Browse files
authored
Merge pull request bevyengine#1 from Weibye/primitive-shapes
Fix markdown lint violations
2 parents 9ef4d2e + f37352e commit bc99e5b

File tree

1 file changed

+25
-22
lines changed

1 file changed

+25
-22
lines changed

rfcs/12-primitive-shapes.md

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ These geometric primitives, or "primitive shapes", are lightweight types for use
66

77
## Motivation
88

9-
This provides a type-level foundation that subsequent engine (and plugin!) features can be built upon incrementally, preventing ecosystem fragmentation. A major goal is to make it possible for engine and game developers to prototype physics, bounding, collision, and raycasting functionality using the same base types. This will make engine integration and cross-plugin interoperability much more feasible, as the engine will have opinionated types that will be natural to implement `into` or `from`. I hope this opens the door to experimentation with multiple physics and bounding acceleration backends.
9+
This provides a type-level foundation that subsequent engine (and plugin!) features can be built upon incrementally, preventing ecosystem fragmentation. A major goal is to make it possible for engine and game developers to prototype physics, bounding, collision, and raycasting functionality using the same base types. This will make engine integration and cross-plugin interoperability much more feasible, as the engine will have opinionated types that will be natural to implement `into` or `from`. I hope this opens the door to experimentation with multiple physics and bounding acceleration backends.
1010

1111
There is significant complexity in the way seemingly equivalent shapes are defined depending on how they are used. By considering these use cases *first*, the goal is that geometric data structures can be composed depending on the needed functionality, with traits used to ensure the right data structure is used for the right task.
1212

@@ -25,7 +25,7 @@ Note that a `Circle2d` does not contain any information about the position of th
2525
| Shape | Mesh | Bounding | Collision |
2626
|--- |---|---|---|
2727
| Sphere || ✔ + Trans | ✔ + Trans |
28-
| Box || ✔ + Trans (AABB) | ✔ + Trans + Rot (OBB) |
28+
| Box || ✔ + Trans (AABB) | ✔ + Trans + Rot (OBB) |
2929
| Capsule ||| ✔ + Trans + Rot |
3030
| Cylinder ||| ✔ + Trans + Rot |
3131
| Cone ||| ✔ + Trans + Rot |
@@ -42,10 +42,10 @@ The difference between the two is somewhat semantic. Both bounding and collision
4242
### Where are the `Transform`s?
4343

4444
In this potential bounding and collision interface, translation and rotation are **not** defined using bevy's `Transform` components, nor are they stored in the base primitive shape types. This is because types that implement `Bounding` and `Collider` must be fully self-contained. This:
45-
46-
* makes the API simpler when using these components in functions and systems
47-
* ensures bounding and collision types use an absolute minimum of memory
48-
* prevents errors caused by nonuniform scale invalidating the shape of the primitive.
45+
46+
* makes the API simpler when using these components in functions and systems
47+
* ensures bounding and collision types use an absolute minimum of memory
48+
* prevents errors caused by nonuniform scale invalidating the shape of the primitive.
4949

5050
Instead, changes to the parent's `GlobalTransform` should be used to derive a new primitive on scale changes - as well as a new translation and rotation if required.
5151

@@ -58,6 +58,7 @@ Both 2d and 3d primitives could implement the `Meshable` trait to provide the ab
5858
```rust
5959
let circle_mesh: Mesh = Circle2d{ radius: 2.0 }.mesh();
6060
```
61+
6162
The base primitive types only define the shape (`Circle2d`) and size (`radius`) of the geometry about the origin. Once generated, the mesh can have a transform applied to it like any other mesh, and it is no longer tied to the primitive that generated it. The `Default::default()` implementation of primitives should be a "unit" variant, such as a circle with diameter 1.0, or a box with all edges of length 1.0.
6263

6364
Meshing could be naturally extended with other libraries or parameters. For example, a sphere by default might use `Icosphere`, but could be extended to generate UV spheres or quad spheres. For 2d types, we could use a crate such as `lyon` to generate 2d meshes from parameterized primitive shapes within the `Meshable` interface.
@@ -82,6 +83,7 @@ This RFC provides independent 2d and 3d primitives. Recall that the purpose of t
8283
/// Stores an angle in radians, and supplies builder functions to prevent errors (from_radians, from_degrees)
8384
struct Angle(f32);
8485
```
86+
8587
### Traits (REFERENCE ONLY!)
8688

8789
**These traits are provided as reference to illustrate how these primitive shape types might be used. The details of implementation and interface should be determined in a separate RFC, PR, or independent prototypes.**
@@ -434,9 +436,10 @@ impl Collider2d for CapsuleCollider2d {}
434436
*/
435437

436438
```
439+
437440
### Bounding and Collision
438441

439-
Primitives colliders and bounding volumes are fully defined in space (in their hypothetical implementation here), and do not use `Transform` or `GlobalTransform`. This is an intentional decision. Because transforms can include nonuniform scale, they are fundamentally incompatible with shape primitives. We could use transforms in the future if the `translation`, `rotation`, and `scale` fields were distinct components, and shape primitives could be bundled with a `translation` or `rotation` if applicable.
442+
Primitives colliders and bounding volumes are fully defined in space (in their hypothetical implementation here), and do not use `Transform` or `GlobalTransform`. This is an intentional decision. Because transforms can include nonuniform scale, they are fundamentally incompatible with shape primitives. We could use transforms in the future if the `translation`, `rotation`, and `scale` fields were distinct components, and shape primitives could be bundled with a `translation` or `rotation` if applicable.
440443

441444
The provided reference implementaiton of bounding and collision types demonstrate how primitive shape types can be composed with other types, triats, or components to build added functionality from shared parts. While the collder and bounding primitives provided as reference are out of scope, they also highlight the incompatibility of shape primitives with the `Transform` component.
442445

@@ -457,7 +460,7 @@ for bounding_volume in bound_vol_query.iter() {
457460

458461
This data structure alone does not ensure the representation is valid; planes could be placed in nonsensical positions. To prevent this, the struct's fields should be made private, and constructors and setters should be provided to ensure `Frustum`s can only be initialized or mutated into valid arrangements.
459462

460-
In addition, by defining the frustum as a set of planes, it is also trivial to support oblique frustums. Oblique frustums are useful for 2d projections used in CAD, as well as in games to take advantage of projection distortion to do things like emphasizing the feeling of speed in a driving game. See the Unity docs: https://docs.unity3d.com/Manual/ObliqueFrustum.html
463+
In addition, by defining the frustum as a set of planes, it is also trivial to support oblique frustums. Oblique frustums are useful for 2d projections used in CAD, as well as in games to take advantage of projection distortion to do things like emphasizing the feeling of speed in a driving game. See the Unity docs: <https://docs.unity3d.com/Manual/ObliqueFrustum.html>
461464

462465
### Ray Casting
463466

@@ -515,10 +518,10 @@ Perhaps most critically, Parry types are opinionated for physics/raycasting use.
515518

516519
## Prior art
517520

518-
- Unity `PrimitiveObjects`: https://docs.unity3d.com/Manual/PrimitiveObjects.html
519-
- Godot `PrimitiveMesh`: https://docs.godotengine.org/en/stable/classes/class_primitivemesh.html#class-primitivemesh
520-
- The popular *Shapes* plugin for Unity https://acegikmo.com/shapes/docs/#line
521-
- Rapier/Parry
521+
* Unity `PrimitiveObjects`: <https://docs.unity3d.com/Manual/PrimitiveObjects.html>
522+
* Godot `PrimitiveMesh`: <https://docs.godotengine.org/en/stable/classes/class_primitivemesh.html#class-primitivemesh>
523+
* The popular *Shapes* plugin for Unity <https://acegikmo.com/shapes/docs/#line>
524+
* Rapier/Parry
522525

523526
Prior art was used to select the most common types of shape primitive, naming conventions, as well as sensible data structures for bounding, collision, and culling.
524527

@@ -530,16 +533,16 @@ What is the best naming scheme, e.g., `2d::Line`/`3d::Line` vs. `Line2d`/`Line3d
530533

531534
### Out of Scope
532535

533-
- Value types, e.g. float vs. fixed is out of scope. This RFC is focused on the core geometry types and is intended to use Bevy's common rendering value types such as `f32`.
534-
- Implementation of bounding, collisions, physics, raycasting, meshing, etc.
536+
* Value types, e.g. float vs. fixed is out of scope. This RFC is focused on the core geometry types and is intended to use Bevy's common rendering value types such as `f32`.
537+
* Implementation of bounding, collisions, physics, raycasting, meshing, etc.
535538

536539
## Future possibilities
537540

538-
- Bounding boxes
539-
- Collisions
540-
- Frustum Culling
541-
- Froxels for forward clustered rendering
542-
- Ray casting
543-
- Physics
544-
- SDF rendering
545-
- Immediate mode debug Rendering (just call `.mesh()`!)
541+
* Bounding boxes
542+
* Collisions
543+
* Frustum Culling
544+
* Froxels for forward clustered rendering
545+
* Ray casting
546+
* Physics
547+
* SDF rendering
548+
* Immediate mode debug Rendering (just call `.mesh()`!)

0 commit comments

Comments
 (0)