Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic spatial module docs #162

Merged
merged 15 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/manual/03_modules/02_spatial/01_transforms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Turning entities into spatialized objects

## Transforms

The first concept to spatialize our entities is to introduce the `TransformComponent`. This stores the spatial information for our entity, its `position`, `rotation`, and `scale`. These properties are bitecs-proxified three.js math objects: a Vector3 for position, a Quaternion for rotation, and another Vector3 for scale.

There are two more properties, the `matrix` and `matrixWorld`, which are three.js Matrix4 properties. `matrix` stores this transform relative to its parent, and `matrixWorld` stores it relative to the absolute origin.

## Hierarchy

Our next component is the `EntityTreeComponent` which stores the parent/child relationships: a `parentEntity` and `children` array of entities. Changing either of these via `setComponent` will automatically update the parent and children entities to reflect this change.

To optimize traditional hierarchy-based calculations, the `TransformSystem` automatically sorts a complete list of all spatial entities in order to utilize `bitecs`’ SoA CPU caching to allow the JavaScript engine to calculate matrices as fast as possible.

## Physics

Physics is split into two systems.

The first is the `PhysicsSystem` which updates the ECS and physics bodies before and after simulation, as well as running the simulation. Substeps can be configured via `PhysicsState`, and the simulation timestep can be configured via `ECSState`. Beyond this, the system has a few neat tricks, such as interpolating kinematic rigidbodies between substeps, and automatically populating and depopulating collision events into the `CollisionComponent`.

The second is the `PhysicsPreTransformSystem` which has two responsibilities, teleporting rigidbodies & colliders if the `TransformComponent` has been mutated, and smoothly interpolating the transform of an entity between physics steps, such that it does not stutter relative to the device framerate.
17 changes: 17 additions & 0 deletions docs/manual/03_modules/02_spatial/02_spatialXRInput.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Spatial Input & WebXR

## Supporting multiple input sources

Input can come from a variety of places:
- **In non-immersive contexts**: It usually comes from a gamepad, mouse, keyboard, or screen touches.
- **In immersive contexts**: It comes from the viewer's 6DOF perspective, and a variety of device-specific extensions such as 6DOF controllers, hands, gamepads, and potentially more.

Since this engine is immersive-first, the abstractions of easily unifying all these input sources are naturally to spatialize them where possible, and using WebXR and other web specifications to guide the API layers.

The first component to introduce is the `InputSourceComponent` which stores the input source information according to the WebXR `XRInputSource` interface, as well as generalized accessor for current button states and entity intersections.

If the input source is spatial, it will have a `TransformComponent` and `XRSpaceComponent`, which stores the spatial information about the source.

If the input source originates from a pointer (mouse or touch), it will store this information in an `InputPointerComponent`, which also stores a reference to the HTML canvas object it originated from.

During the input system phase, the ClientInputSystem calculates all the runtime information, such as transform and intersections for input sources. For each intersection, it also stores the intersecting input source entity on the first intersected entity if the `InputComponent` exists on that entity, which effectively specifies an entity is an input receiver. Input can be "captured" globally by an entity by mutating the `capturingEntity` property on `InputState`, which enforces that only that entity should receive input.
12 changes: 12 additions & 0 deletions docs/manual/03_modules/02_spatial/03_objects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Objects

## Meshes

So far, we have only specified how things are spatialized, but not how to describe the physics properties of the objects themselves.

Meshes compose two fundamental data structures into object instances: geometries, which describe the topology of an object's surface, and materials, which describe the details that surface.

<!-- TODO
## Geometries
## Materials
-->
13 changes: 13 additions & 0 deletions docs/manual/03_modules/02_spatial/04_cameraSceneRendering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Rendering Scenes

The `RendererComponent` defines the parameters for rendering a scene to render target (such as an HTML canvas or WebXR layer).

Scenes are simply defined as entity hierarchies. The `SceneComponent` is used to specify which scene entities to render. Only the root of an entity hierarchy needs to be specified.

Once an entity has both of these components, only a `CameraComponent` is needed to actually render a scene. The camera provides a perspective from which to render the scene. The `CameraComponent` specifies an ArrayCamera, which allows rendering one or more perspectives simultaneously.

Upon the `WebGLRendererSystem` running, it will aggregate the list of entities to render, and get the underlying objects from the GroupComponent into a flat list. This list is iterated, and pulls out a few extra parameters. The `EnvironmentMapComponent` specifies the environment map to use for meshes that do not have an environment map already specified. The `BackgroundComponent` specifies the skybox to render, either a Color, a Texture, or a CubeTexture. The `FogComponent` specifies the fog parameters to use.

<!-- TODO
- Postprocessing
-->
3 changes: 0 additions & 3 deletions docs/manual/03_modules/02_spatial/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,4 @@ sidebar_label: Spatial
import DocCardList from '@theme/DocCardList'

# Spatial Module
<!--
TODO: Uncomment to enable the DocCardList for the subfolder
<DocCardList />
-->
Loading