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

OMI_physics_shape and OMI_physics_body #2258

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
19 changes: 19 additions & 0 deletions extensions/2.0/Vendor/OMI_physics_body/README.collider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# OMI_physics_body Collider Property

If a node has the `"collider"` property defined, it is a solid collider node that objects can collide with.

Collider nodes are recommended to be direct children of the "body" node (the one that defines motion), if any. This results in a very clear, simple, and portable document structure, which ensures each collider is transformed relative to the body via a single glTF node transform. However, collider nodes may also be defined as indrect descendants of the body node, and may be defined on the same node as the body node. If multiple ancestors are "body" nodes, only the nearest ancestor uses the collider. Implementations must support all of these cases in order to be compliant.

## Collider Properties

| | Type | Description | Default value |
| --------- | --------- | ----------------------------------------------------- | ------------- |
| **shape** | `integer` | The index of the shape to use as the collision shape. | -1 |

### Shape

The `"shape"` property is an integer index that references a shape in the document-level shapes array as defined by the `OMI_physics_shape` extension. If not specified or -1, this node has no collider shape, but may be the parent of other nodes that do have collider shapes, and can combine those nodes into one collider (this may be a body or compound collider depending on the engine).

## JSON Schema

See [schema/node.OMI_physics_body.collider.schema.json](schema/node.OMI_physics_body.collider.schema.json) for the collider properties JSON schema.
130 changes: 130 additions & 0 deletions extensions/2.0/Vendor/OMI_physics_body/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# OMI_physics_body

## Contributors

* Aaron Franke, The Mirror Megaverse Inc.
* Mauve Signweaver, Mauve Software Inc.

## Status

Open Metaverse Interoperability Group Stage 1 Proposal

## Dependencies

Written against the glTF 2.0 spec.

Depends on the `OMI_physics_shape` spec to be useful.

## Overview

This extension allows for specifying physics bodies in glTF scenes.

Nodes with the `OMI_physics_body` extension may define motion, collider, and trigger properties.

If a node with a collider shape does not have a motion property, , it should be a static solid object that does not move.

### Example:

This example defines a static body node which has a single box collider as a child:

```json
{
"asset": {
"version": "2.0"
},
"extensions": {
"OMI_physics_shape": {
"shapes": [
{
"type": "box",
"box": {
"size": [1, 2, 3]
}
}
]
}
},
"extensionsUsed": [
"OMI_physics_body",
"OMI_physics_shape"
],
"nodes": [
{
"extensions": {
"OMI_physics_body": {
"motion": {
"type": "dynamic"
},
"collider": {
"shape": 0
}
}
},
"name": "DynamicBox"
}
],
"scene": 0,
"scenes": [{ "nodes": [0] }]
}
```

The above example shows dynamic motion and collision shape specified on one node. A nearly identical example using 2 nodes can be found in [examples/basic/dynamic_box.gltf](examples/basic/dynamic_box.gltf).

More example assets can be found in the [examples/](examples/) folder. All of these examples use both `OMI_physics_shape` and `OMI_physics_body`.

## glTF Schema Updates

This extension consists of a new `OMI_physics_body` data structure which can be added to a glTF node.

The extension must also be added to the glTF's `extensionsUsed` array and because it is optional, it does not need to be added to the `extensionsRequired` array.

The extension is intended to be used together with `OMI_physics_shape`, which defines the shapes used by the `"shape"` properties inside of the `"collider"` and `"trigger"` sub-JSON properties.

### Property Summary

| | Type | Description | Default value |
| ------------ | ---- | ------------------------------------------------------------ | ------------- |
| **motion** | JSON | If present, this node has its motion controlled by physics. | `null` |
| **collider** | JSON | If present, this node is solid and can be collided with. | `null` |
| **trigger** | JSON | If present, this node is non-solid and can act as a trigger. | `null` |

Each of these properties are recommended to be defined on separate nodes. This results in a very clear, simple, and portable document structure, and ensures that each behavior has its own transform. However, they may also be all defined on the same node. Implementations must support all of these cases in order to be compliant.

#### Motion

If a node has the `"motion"` property defined, its transform is driven by the physics engine.

The list of motion properties and their details can be found in the [README.motion.md](README.motion.md) file.

#### Collider

If a node has the `"collider"` property defined, it is a solid collider node that objects can collide with.

The list of collider properties and their details can be found in the [README.collider.md](README.collider.md) file.

#### Trigger

If a node has the `"trigger"` property defined, it is a non-solid trigger that can detect when objects enter it.

The list of trigger properties and their details can be found in the [README.trigger.md](README.trigger.md) file.

### JSON Schema

See [schema/node.OMI_physics_body.schema.json](schema/node.OMI_physics_body.schema.json) for the main schema, and these for the sub-JSON schemas:
* Motion: [schema/node.OMI_physics_body.motion.schema.json](schema/node.OMI_physics_body.motion.schema.json)
* Collider: [schema/node.OMI_physics_body.collider.schema.json](schema/node.OMI_physics_body.collider.schema.json)
* Trigger: [schema/node.OMI_physics_body.trigger.schema.json](schema/node.OMI_physics_body.trigger.schema.json)

## Known Implementations

* Godot Engine: https:/godotengine/godot/pull/78967

## Resources:

* Unity colliders: https://docs.unity3d.com/Manual/CollidersOverview.html
* Unreal Engine Physics: https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/Physics/Collision/Overview/
* Godot Physics Body: https://docs.godotengine.org/en/stable/classes/class_physicsbody.html
* Godot Area: https://docs.godotengine.org/en/stable/classes/class_area.html
* Godot RigidBody3D: https://docs.godotengine.org/en/latest/classes/class_rigidbody3d.html
* Wikipedia Moment of Inertia: https://en.wikipedia.org/wiki/Moment_of_inertia
* Wikipedia Rigid Body Dynamics: https://en.wikipedia.org/wiki/Rigid_body_dynamics
73 changes: 73 additions & 0 deletions extensions/2.0/Vendor/OMI_physics_body/README.motion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# OMI_physics_body Motion Property

If a node has the `"motion"` property defined, its transform is driven by the physics engine.

* Descendant nodes should move with that node. The physics engine should treat them as part of a single body.
* If a descendant node has its own motion property, that node should be treated as an independent body during simulation. There is no implicit requirement that it follows its "parent" rigid body.
* If a node's transform is animated by animations in the file, those animations should take priority over the physics simulation.

## Motion Properties

| | Type | Description | Default value |
| ---------------------- | ----------- | -------------------------------------------------------------------- | -------------------- |
| **type** | `string` | The type of the physics body as a string. | Required, no default |
| **mass** | `number` | The mass of the physics body in kilograms. | 1.0 |
| **linearVelocity** | `number[3]` | The initial linear velocity of the body in meters per second. | [0.0, 0.0, 0.0] |
| **angularVelocity** | `number[3]` | The initial angular velocity of the body in radians per second. | [0.0, 0.0, 0.0] |
| **centerOfMass** | `number[3]` | The center of mass offset from the origin in meters. | [0.0, 0.0, 0.0] |
| **inertiaDiagonal** | `number[3]` | The inertia around principle axes in kilogram meter squared (kg⋅m²). | [0.0, 0.0, 0.0] |
| **inertiaOrientation** | `number[4]` | The inertia orientation as a Quaternion. | [0.0, 0.0, 0.0, 1.0] |

### Motion Types

The `"type"` property is a lowercase string that defines what type of physics body this is. Different types of physics bodies have different interactions with physics systems and other bodies within a scene.

Here is a table listing the mapping between the `OMI_physics_body` type and the equivalent types in major game engines.

| Body Type | Unity | Godot 3 | Godot 4 | Unreal |
| --------- | --------------------- | ------------- | ---------------- | -------------------------------------- |
| Static | Collider | StaticBody | StaticBody3D | WorldStatic, Simulate Physics = false |
| Kinematic | Rigidbody.isKinematic | KinematicBody | AnimatableBody3D | WorldDynamic, Simulate Physics = false |
| Dynamic | Rigidbody | RigidBody | RigidBody3D | PhysicsBody, Simulate Physics = true |

#### Static

Static bodies can be collided with, but do not have simulated movement. They are usually used for level geometry. Specifying a static body is optional, as nodes with collider properties are assumed to be static without itself or a parent node having the motion property.

#### Kinematic

Kinematic bodies can be collided with, and can be moved using scripts or animations. They can be used for moving platforms.

#### Dynamic

Dynamic bodies are bodies simulated with [rigid body dynamics](https://en.wikipedia.org/wiki/Rigid_body_dynamics). They collide with other bodies, and move around on their own in the physics simulation. They are affected by gravity. They can be used for props that move around in the world.

### Mass

The `"mass"` property is a number that defines how much mass this physics body has in kilograms. Not all body types can make use of mass, such as triggers or non-moving bodies, in which case the mass can be ignored. If not specified, the default value is 1 kilogram.

### Linear Velocity

The `"linearVelocity"` property is an array of three numbers that defines how much linear velocity this physics body starts with in meters per second. Not all body types can make use of linear velocity, such as non-moving bodies, in which case the linear velocity can be ignored. If not specified, the default value is zero.

### Angular Velocity

The `"angularVelocity"` property is an array of three numbers that defines how much angular velocity this physics body starts with in radians per second. Not all body types can make use of angular velocity, such as non-moving bodies, in which case the angular velocity can be ignored. If not specified, the default value is zero.

### Center of Mass

The `"centerOfMass"` property is an array of three numbers that defines the position offset in meters of the center of mass in the body's local space.

This property is useful when converting assets with a center of mass, but when creating new assets it is recommended to leave the center of mass at the body's origin. Some physics engines support the center of mass being offset from the origin, but not all of them do. Implementations without support for a center of mass offset would have to adjust the node positions to make this work, which may be undesired.

### Inertia Diagonal

The `"inertiaDiagonal"` property is an array of 3 numbers that defines the inertia around the principle axes of the body in kilogram meter squared (kg⋅m²). We specify "tensor" in the name because this defines inertia in multiple directions and is different from linear momentum inertia. Only the "dynamic" motion type can make use of inertia. If zero or not specified, the inertia should be automatically calculated by the physics engine.

### Inertia Orientation

The `"inertiaOrientation"` property is an array of 4 numbers that defines a Quaternion for orientation of the inertia's principle axes relative to the body's local space. If not specified or set to the default value of `[0.0, 0.0, 0.0, 1.0]`, no rotation is applied, the inertia's principle axes are aligned with the body's local space axes.

## JSON Schema

See [schema/node.OMI_physics_body.motion.schema.json](schema/node.OMI_physics_body.motion.schema.json) for the motion properties JSON schema.
21 changes: 21 additions & 0 deletions extensions/2.0/Vendor/OMI_physics_body/README.trigger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# OMI_physics_body Trigger Property

If a node has the `"trigger"` property defined, it has a non-solid trigger shape that can detect when objects enter it.

Triggers are not solid and do not "collide" with other objects, but can generate events when another physics body "enters" them. For example, a "goal" area which triggers whenever a ball gets thrown into it.

Trigger nodes are recommended to not be defined on the same node that defines `"motion"` or `"collider"`. This results in a very clear, simple, and portable document structure. If a trigger is desired to have motion, define the trigger on a child node of the node with the motion property.

## Trigger Properties

| | Type | Description | Default value |
| --------- | --------- | --------------------------------------------------- | ------------- |
| **shape** | `integer` | The index of the shape to use as the trigger shape. | -1 |

### Shape

The `"shape"` property is an integer index that references a shape in the document-level shapes array as defined by the `OMI_physics_shape` extension. If not specified or -1, this node has no trigger shape, but may be the parent of other nodes that do have trigger shapes, and should combine those nodes into one trigger (this may be a body or compound trigger depending on the engine).

## JSON Schema

See [schema/node.OMI_physics_body.trigger.schema.json](schema/node.OMI_physics_body.trigger.schema.json) for the trigger properties JSON schema.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"asset": {
"version": "2.0"
},
"extensions": {
"OMI_physics_shape": {
"shapes": [
{
"type": "box",
"box": {
"size": [1, 2, 3]
}
}
]
}
},
"extensionsUsed": [
"OMI_physics_body",
"OMI_physics_shape"
],
"nodes": [
{
"children": [1],
"extensions": {
"OMI_physics_body": {
"motion": {
"type": "dynamic"
}
}
},
"name": "DynamicBox"
},
{
"extensions": {
"OMI_physics_body": {
"collider": {
"shape": 0
}
}
},
"name": "BoxShape"
}
],
"scene": 0,
"scenes": [{ "nodes": [0] }]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"asset": {
"version": "2.0"
},
"extensions": {
"OMI_physics_shape": {
"shapes": [
{
"type": "box",
"box": {
"size": [1, 1, 1]
}
}
]
}
},
"extensionsUsed": [
"OMI_physics_body",
"OMI_physics_shape"
],
"nodes": [
{
"extensions": {
"OMI_physics_body": {
"trigger": {
"shape": 0
}
}
},
"name": "TriggerBox"
}
],
"scene": 0,
"scenes": [{ "nodes": [0] }]
}
Loading