Open Metaverse Interoperability Group Stage 2 Proposal
Written against the glTF 2.0 spec.
Optionally depends on the OMI_physics_body
spec for triggers.
This extension allows defining a glTF node as a seat which a humanoid character can sit on.
A seat is defined by specifying the back, foot, and knee positions on the seat from which can be derived the IK positions and directions for placing a humanoid character on that seat. Optionally, the angle between the upper leg and spine can also be defined. This definition supports seats placed in any orientation and supports characters of any size sitting on them.
In addition to being defined independently, the OMI_seat
extension can be defined on an OMI_physics_body
node with the type set to trigger. When OMI_seat
is on a trigger, the trigger should be treated as an entry for the seat, such that a player activating that trigger should cause that player to enter the seat.
Alternate seated positions, such as a tiny character with straight legs on top of the seat, or a character with their legs crossed on top of the seat, are not the recommended use cases of the seat definition, but are not forbidden if an app wants a character to sit in an unusual position. The primary purpose of this spec is to define the seat itself; how characters sit on that seat is secondary, and the fine details are up to the implementation.
This extension does not define any animations for entering or exiting the seat. It also does not define anything that a character’s arms, head, tail, or chest should be doing, it only defines information about the seat itself intended to be used to place the legs on the seat.
This example defines a seat using a simple chair facing positive Z. This is the same as the simple_chair_pos_z.gltf
example, but without the mesh data.
{
"asset": {
"version": "2.0"
},
"extensionsUsed": [
"OMI_seat"
],
"nodes": [
{
"mesh": 0,
"name": "SimpleChairMesh"
},
{
"children": [
0
],
"name": "SimpleChairPosZ",
"extensions": {
"OMI_seat": {
"back": [0, 0.33, -0.24],
"foot": [0, -0.25, 0.3],
"knee": [0, 0.33, 0.3]
}
}
}
],
"scene": 0,
"scenes": [{ "nodes": [1] }],
}
More example assets can be found in the examples/ folder.
This extension consists of one new data structure for defining the seat limits, "OMI_seat"
. The key "OMI_seat"
can be added to the node-level "extensions"
of a glTF node to define a seat.
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.
Type | Description | Default value | |
---|---|---|---|
back | number[3] |
The position limit on the seat corresponding to the character’s back in local space. | Required, no default |
foot | number[3] |
The position limit on the seat corresponding to the character’s feet in local space. | Required, no default |
knee | number[3] |
The base position on the seat corresponding to the character’s knees in local space. | Required, no default |
angle | number |
The angle between the spine and back-knee line in radians. | 1.570796… (τ/4 or π/2 rad, 90 deg) |
To avoid confusion with different standards of which direction is the forward direction, we define the forward direction by the direction from the back position to the knee position. The up direction is a vector perpendicular to the forward direction such that the direction from the knee to the foot points down. The back, foot, and knee positions should not be colinear or nearly colinear.
The "back"
property is a vector as a three-number array that defines the position limit of the character’s back and hips in local space.
The character’s upper leg (thigh) bones are typically placed on lines parallel to the line between the knee and back points, with the lines offset upward based on the thickness of the upper leg and offset to the side based on the desired distance between each leg. If the upper leg is smaller than this line, then the knees are aligned with the knee point, and the hips are moved forward in-between the knee and back points. If the upper leg is larger than this line, then the hips are aligned with the back point, the knees are moved forward farther than the knee point. The knees may also be moved up depending on the foot-knee constraint.
The "foot"
property is a vector as a three-number array that defines the position limit of the character’s feet and lower legs in local space.
The character’s lower leg (calf) bones are typically placed on lines parallel to the line between the knee and foot points, with the lines offset forward based on the thickness of the lower leg and offset to the side based on the desired distance between each leg. If the lower leg is smaller than this line, then the knees are aligned with the knee point, and the feet are moved upward in-between the knee and back points. If the lower leg is larger than this line, then the feet are aligned with the foot point, and the knee is moved upward farther than the knee point. The knees may also be moved forward depending on the back-knee constraint.
The "knee"
property is a vector as a three-number array that defines the base position of the character’s knees in local space.
The "angle"
property is a number that defines the angle between the spine and the line connecting the back and knee positions. If not specified, the default value is 1.57079632679489662
or τ/4 or π/2, which is 90 degrees represented in radians.
This is an angle instead of a position because:
This property only needs to be defined when the desired angle between the spine and back-knee line is not 90 degrees. For example, a reclining chair that has a back tilted so the character could lie back should have this defined.
The positions defined above can be used to uniquely find other vectors used to place a character on the seat.
These are the directions of the seat itself, the actual directions a character ends up at may be different. The specifics of this depend on the IK system used. However, one common feature is the need to offset from the seat based on the thickness of the legs in order to determine the points to use for IK, so that we avoid the character’s legs being inside of the seat itself.
In a nutshell, the legs sit as close to the seat as possible while not clipping though it, therefore we offset by the leg thickness, otherwise the leg bones would be exactly on the seat’s surface. We want to keep the seat’s points exactly on the seat and have the character legs offset from the seat’s points so that we don’t play favorites for any particular leg size.
See schema/node.OMI_seat.schema.json for the schema.