From 32ec46dd73e1caf90fa99a5203341c7312e54e89 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Thu, 12 Sep 2024 03:51:58 -0700 Subject: [PATCH] Change capsules and cylinders to have separate top and bottom radiuses --- extensions/2.0/OMI_physics_shape/README.md | 52 ++++++++++++------- .../examples/capsule_collider.gltf | 5 +- .../examples/cylinder_collider.gltf | 3 +- .../schema/glTF.OMI_physics_shape.schema.json | 4 +- ...TF.OMI_physics_shape.shape.box.schema.json | 9 +++- ...MI_physics_shape.shape.capsule.schema.json | 18 +++++-- ...I_physics_shape.shape.cylinder.schema.json | 18 +++++-- .../glTF.OMI_physics_shape.shape.schema.json | 4 +- ...OMI_physics_shape.shape.sphere.schema.json | 4 +- 9 files changed, 80 insertions(+), 37 deletions(-) diff --git a/extensions/2.0/OMI_physics_shape/README.md b/extensions/2.0/OMI_physics_shape/README.md index 20e721b..480d340 100644 --- a/extensions/2.0/OMI_physics_shape/README.md +++ b/extensions/2.0/OMI_physics_shape/README.md @@ -63,18 +63,20 @@ The extension must also be added to the glTF's `extensionsUsed` array and becaus The main data structure `glTF.OMI_physics_shape.shape.schema.json` defines a type property. -| | Type | Description | Default value | -| --------------| ----------- | -------------------------------------------------------------------------- | -------------------- | -| **type** | `string` | The type of the physics shape as a string. | Required, no default | +| | Type | Description | Default value | +| -------- | -------- | ------------------------------------------ | -------------------- | +| **type** | `string` | The type of the physics shape as a string. | Required, no default | In addition to the type, a key with the same name as the type can be used to define a sub-JSON with the details of the shape. Which sub-properties are allowed depend on which shape type is being used. The possible properties are described in the following table. -| | Type | Description | Default value | Valid on | -| --------------| ----------- | -------------------------------------------------------------------------- | -------------------- | ------------------------- | -| **size** | `number[3]` | The size of the box shape in meters. | [1.0, 1.0, 1.0] | Box | -| **radius** | `number` | The radius of the shape in meters. | 0.5 | Sphere, capsule, cylinder | -| **height** | `number` | The height of the shape in meters. | 2.0 | Capsule, cylinder | -| **mesh** | `number` | The index of the glTF mesh in the document to use as a mesh shape. | -1 | Trimesh, convex | +| | Type | Description | Default value | Valid on | +| ---------------- | ----------- | ------------------------------------------------------------------ | --------------- | ----------------- | +| **size** | `number[3]` | The size of the box shape in meters. | [1.0, 1.0, 1.0] | Box | +| **radius** | `number` | The radius of the sphere shape in meters. | 0.5 | Sphere | +| **radiusBottom** | `number` | The radius of the bottom disc or hemisphere in meters. | 0.5 | Capsule, cylinder | +| **radiusTop** | `number` | The radius of the top disc or hemisphere in meters. | 0.5 | Capsule, cylinder | +| **height** | `number` | The mid-height of the cylindrical part of the shape in meters. | 1.0 or 2.0 | Capsule, cylinder | +| **mesh** | `number` | The index of the glTF mesh in the document to use as a mesh shape. | -1 | Trimesh, convex | If a key for the type is missing, or a sub-JSON key is missing, implementations should use the default value. A mesh index of -1 means invalid. @@ -105,13 +107,21 @@ Sphere shapes describe a uniform "ball" shape. They have a `radius` property whi #### Capsule -Capsule shapes describe a "pill" shape. They have a `radius` and `height` property. The height is aligned with the node's local vertical axis. If it's desired to align it along a different axis, rotate the glTF node. If the `radius` property is omitted, the default radius is `0.5`, and if the `height` property is omitted, the default height is `2.0`. The height describes the total height from bottom to top. The height of the capsule must be at least twice as much as the radius. The "mid-height" between the centers of each spherical cap end can be found with `height - radius * 2.0`. +Capsule shapes describe a "pill" shape. They have `height`, `radiusBottom`, and `radiusTop` properties. If either of the radius properties are omitted, the default radius is `0.5`, and if the `height` property is omitted, the default height is `1.0`. + +The `height` property describes the "mid height", the distance between the centers of the two capping hemispheres. The full height from the bottom-most point to the top-most point can be found with `height + radiusBottom + radiusTop`, meaning that a capsule with default values has a full height of 2.0 meters. The height is aligned with the node's local vertical axis. If it's desired to align it along a different axis, rotate the glTF node. + +The `radiusBottom` and `radiusTop` properties are recommended to be set to the same value. Having these be different values results in a shape that is not a regular capsule, but a "tapered capsule". Tapered capsules are not supported by all game engines, so using them may result in importers approximating the tapered capsule shape with a convex hull shape. #### Cylinder -Cylinder shapes describe a "tall circle" shape. They are similar in structure to capsules, they have a `radius` and `height` property. The height is aligned with the node's local vertical axis. If it's desired to align it along a different axis, rotate the glTF node. If the `radius` property is omitted, the default radius is `0.5`, and if the `height` property is omitted, the default height is `2.0`. +Cylinder shapes describe a "tall circle" shape. They are similar in structure to capsules, they have `height`, `radiusBottom`, and `radiusTop` properties. If the `radius` property is omitted, the default radius is `0.5`, and if the `height` property is omitted, the default height is `2.0`. + +The `height` property of a cylinder describes the total height, the distance between the center of the bottom disc and the center of the top disc. The height is aligned with the node's local vertical axis. If it's desired to align it along a different axis, rotate the glTF node. + +The `radiusBottom` and `radiusTop` properties are recommended to be set to the same value. Having these be different values results in a shape that is not a regular cylinder, but a "tapered cylinder". Tapered cylinders are not supported by all game engines, so using them may result in importers approximating the tapered cylinder shape with a convex hull shape. -The use of cylinder is discouraged if another shape would work well in its place. Cylinders are harder to calculate than boxes, spheres, and capsules. Not all game engines support cylinder shapes. Engines that do not support cylinder shapes should use an approximation, such as a convex hull roughly shaped like a cylinder. Cylinders over twice as tall as they are wide can use another approximation: a convex hull combined with an embedded capsule (to allow for smooth rolling), by copying the cylinder's values into a new capsule shape. +The use of cylinder is discouraged if another shape would work well in its place. Cylinders are harder to calculate than boxes, spheres, and capsules. Not all game engines support cylinder shapes. Engines that do not support cylinder shapes should use an approximation, such as a convex hull roughly shaped like a cylinder. Cylinders over twice as tall as they are wide can use another approximation: a convex hull combined with an embedded capsule to allow for smooth rolling, by copying the cylinder's radius values, and setting the capsule's full height to the cylinder's height, meaning setting the capsule's mid height property to `height - radiusBottom - radiusTop`. #### Convex @@ -131,14 +141,16 @@ Avoid using a trimesh shape for most objects, they are the slowest shapes to cal The following JSON pointers are defined representing mutable properties defined by this extension, for use with the glTF Object Model including extensions such as `KHR_animation_pointer` and `KHR_interactivity`. -| JSON Pointer | Object Model Type | -| --------------------------------------------------------- | ----------------- | -| `/extensions/OMI_physics_shape/shapes/{}/box/size` | `float3` | -| `/extensions/OMI_physics_shape/shapes/{}/sphere/radius` | `float` | -| `/extensions/OMI_physics_shape/shapes/{}/capsule/radius` | `float` | -| `/extensions/OMI_physics_shape/shapes/{}/capsule/height` | `float` | -| `/extensions/OMI_physics_shape/shapes/{}/cylinder/radius` | `float` | -| `/extensions/OMI_physics_shape/shapes/{}/cylinder/height` | `float` | +| JSON Pointer | Object Model Type | +| --------------------------------------------------------------- | ----------------- | +| `/extensions/OMI_physics_shape/shapes/{}/box/size` | `float3` | +| `/extensions/OMI_physics_shape/shapes/{}/sphere/radius` | `float` | +| `/extensions/OMI_physics_shape/shapes/{}/capsule/height` | `float` | +| `/extensions/OMI_physics_shape/shapes/{}/capsule/radiusBottom` | `float` | +| `/extensions/OMI_physics_shape/shapes/{}/capsule/radiusTop` | `float` | +| `/extensions/OMI_physics_shape/shapes/{}/cylinder/height` | `float` | +| `/extensions/OMI_physics_shape/shapes/{}/cylinder/radiusBottom` | `float` | +| `/extensions/OMI_physics_shape/shapes/{}/cylinder/radiusTop` | `float` | Additionally, the following JSON pointers are defined for read-only properties: diff --git a/extensions/2.0/OMI_physics_shape/examples/capsule_collider.gltf b/extensions/2.0/OMI_physics_shape/examples/capsule_collider.gltf index 2937462..6465df0 100644 --- a/extensions/2.0/OMI_physics_shape/examples/capsule_collider.gltf +++ b/extensions/2.0/OMI_physics_shape/examples/capsule_collider.gltf @@ -8,8 +8,9 @@ { "type": "capsule", "capsule": { - "height": 2.0, - "radius": 0.5 + "height": 1.0, + "radiusBottom": 0.5, + "radiusTop": 0.5 } } ] diff --git a/extensions/2.0/OMI_physics_shape/examples/cylinder_collider.gltf b/extensions/2.0/OMI_physics_shape/examples/cylinder_collider.gltf index d1a416c..01ae398 100644 --- a/extensions/2.0/OMI_physics_shape/examples/cylinder_collider.gltf +++ b/extensions/2.0/OMI_physics_shape/examples/cylinder_collider.gltf @@ -9,7 +9,8 @@ "type": "cylinder", "cylinder": { "height": 2.0, - "radius": 0.5 + "radiusBottom": 0.5, + "radiusTop": 0.5 } } ] diff --git a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.schema.json b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.schema.json index 4f58102..28ee67f 100644 --- a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.schema.json +++ b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.schema.json @@ -8,10 +8,10 @@ "properties": { "shapes": { "type": "array", - "description": "An array of shapes that can be referenced by nodes.", + "description": "An array of physics shape resources that can be referenced by nodes.", "items": { "type": "object", - "$ref": "shape.schema.json" + "$ref": "glTF.OMI_physics_shape.shape.schema.json" }, "minItems": 1 }, diff --git a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.box.schema.json b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.box.schema.json index 37961c4..b98caf6 100644 --- a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.box.schema.json +++ b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.box.schema.json @@ -8,7 +8,14 @@ "properties": { "size": { "type": "array", - "description": "Three number array representing the width, height, and depth of the box (x, y, z)." + "description": "Three number array representing the width, height, and depth of the box (x, y, z).", + "items": { + "type": "number", + "exclusiveMinimum": 0.0 + }, + "minItems": 3, + "maxItems": 3, + "default": [ 1.0, 1.0, 1.0 ] }, "extensions": { }, "extras": { } diff --git a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.capsule.schema.json b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.capsule.schema.json index 27e9d96..48e23f9 100644 --- a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.capsule.schema.json +++ b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.capsule.schema.json @@ -6,13 +6,23 @@ "description": "Parameters describing a capsule physics shape.", "allOf": [ { "$ref": "glTFProperty.schema.json" } ], "properties": { - "radius": { + "height": { "type": "number", - "description": "The radius to use for the capsule shape." + "description": "The mid height of the capsule shape, the distance between the centers of the two capping hemispheres.", + "minimum": 0.0, + "default": 1.0 }, - "height": { + "radiusBottom": { + "type": "number", + "description": "The radius of the bottom of the capsule (the hemisphere located along -Y) in meters.", + "minimum": 0.0, + "default": 0.5 + }, + "radiusTop": { "type": "number", - "description": "The full height of the capsule shape." + "description": "The radius of the top of the capsule (the hemisphere located along +Y) in meters.", + "minimum": 0.0, + "default": 0.5 }, "extensions": { }, "extras": { } diff --git a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.cylinder.schema.json b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.cylinder.schema.json index bfa0d87..1f638f8 100644 --- a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.cylinder.schema.json +++ b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.cylinder.schema.json @@ -6,13 +6,23 @@ "description": "Parameters describing a cylinder physics shape.", "allOf": [ { "$ref": "glTFProperty.schema.json" } ], "properties": { - "radius": { + "height": { "type": "number", - "description": "The radius to use for the cylinder shape." + "description": "The height of the cylinder shape in meters, the distance between the centers of the two capping discs.", + "minimum": 0.0, + "default": 2.0 }, - "height": { + "radiusBottom": { + "type": "number", + "description": "The radius of the bottom of the cylinder (the disc located along -Y) in meters.", + "minimum": 0.0, + "default": 0.5 + }, + "radiusTop": { "type": "number", - "description": "The height of the cylinder shape." + "description": "The radius of the top of the cylinder (the disc located along +Y) in meters.", + "minimum": 0.0, + "default": 0.5 }, "extensions": { }, "extras": { } diff --git a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.schema.json b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.schema.json index 4e7d41f..317ac17 100644 --- a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.schema.json +++ b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.schema.json @@ -3,12 +3,12 @@ "$id": "glTF.OMI_physics_shape.shape.schema.json", "title": "OMI_physics_shape Shape Resource", "type": "object", - "description": "Defines a physics shape resource.", + "description": "Defines a physics shape resource that can be referenced by nodes.", "allOf": [ { "$ref": "glTFChildOfRootProperty.schema.json" } ], "properties": { "type": { "type": "string", - "description": "The type of shape this node represents.", + "description": "Specifies the shape type of this physics shape.", "enum": [ "box", "sphere", diff --git a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.sphere.schema.json b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.sphere.schema.json index d06edc7..c33aad1 100644 --- a/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.sphere.schema.json +++ b/extensions/2.0/OMI_physics_shape/schema/glTF.OMI_physics_shape.shape.sphere.schema.json @@ -8,7 +8,9 @@ "properties": { "radius": { "type": "number", - "description": "The radius to use for the sphere shape." + "description": "The radius to use for the sphere shape in meters.", + "minimum": 0.0, + "default": 0.5 }, "extensions": { }, "extras": { }