Skip to content

Commit

Permalink
Add OMI_physics_body extension validation
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronfranke committed May 5, 2023
1 parent 0658993 commit f700fac
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 3 deletions.
4 changes: 3 additions & 1 deletion ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@
|NON_REQUIRED_EXTENSION|Extension '`%1`' cannot be optional.|Error|
|OMI_COLLIDER_INVALID_CAPSULE_HEIGHT|The capsule height must be at least twice the radius.|Error|
|OMI_COLLIDER_TRIMESH_TRIGGER|This collider is both a trimesh and a trigger. This is valid but not recommended since trimeshes do not have an interior volume and the trigger may not work as expected.|Information|
|OMI_PHYSICS_BODY_INVALID_INERTIA_TENSOR|This physics body has an invalid inertia tensor. The inertia tensor must be a symmetric 3x3 matrix.|Error|
|OMI_PHYSICS_BODY_MISSING_COLLIDER|This physics body does not have any colliders. This is valid but body will not collide with anything.|Information|
|ROTATION_NON_UNIT|Rotation quaternion must be normalized.|Error|
|SHARES_NODE_WITH|`%1` must be on its own glTF node, it cannot be on the same glTF node as `%2`.|Error|
|SHARES_NODE_WITH|`%1` must be on its own glTF node, it cannot be on the same glTF node as `%2`. Move the `%3` to a child node.|Error|
|SKIN_NO_COMMON_ROOT|Joints do not have a common root.|Error|
|SKIN_SKELETON_INVALID|Skeleton node is not a common root.|Error|
|UNKNOWN_ASSET_MAJOR_VERSION|Unknown glTF major asset version: `%1`.|Error|
Expand Down
17 changes: 16 additions & 1 deletion lib/src/errors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,8 @@ class SemanticError extends IssueType {
static final SemanticError sharesNodeWith = SemanticError._(
'SHARES_NODE_WITH',
(args) => '${args[0]} must be on its own glTF node, '
'it cannot be on the same glTF node as ${args[1]}.',
'it cannot be on the same glTF node as ${args[1]}.'
'${args.length > 2 ? ' Move the ${args[2]} to a child node.' : ''}',
Severity.Error);

static final SemanticError extraProperty = SemanticError._(
Expand Down Expand Up @@ -553,6 +554,20 @@ class SemanticError extends IssueType {
'interior volume and the trigger may not work as expected.',
Severity.Information);

static final SemanticError omiPhysicsBodyMissingCollider =
SemanticError._(
'OMI_PHYSICS_BODY_MISSING_COLLIDER',
(args) => 'This physics body does not have any colliders. '
'This is valid but body will not collide with anything.',
Severity.Information);

static final SemanticError omiPhysicsBodyInvalidInertiaTensor =
SemanticError._(
'OMI_PHYSICS_BODY_INVALID_INERTIA_TENSOR',
(args) => 'This physics body has an invalid inertia tensor. '
'The inertia tensor must be a symmetric 3x3 matrix.',
Severity.Error);

SemanticError._(String type, ErrorFunction message,
[Severity severity = Severity.Error])
: super(type, message, severity);
Expand Down
139 changes: 139 additions & 0 deletions lib/src/ext/OMI_physics_body/omi_physics_body.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright 2022 The Khronos Group Inc.
//
// SPDX-License-Identifier: Apache-2.0

library gltf.extensions.omi_physics_body;

import 'package:gltf/src/base/gltf_property.dart';
import 'package:gltf/src/ext/extensions.dart';

const String OMI_PHYSICS_BODY = 'OMI_physics_body';

const String MASS = 'mass';
const String LINEAR_VELOCITY = 'linearVelocity';
const String ANGULAR_VELOCITY = 'angularVelocity';
const String INERTIA_TENSOR = 'inertiaTensor';

const String STATIC = 'static';
const String KINEMATIC = 'kinematic';
const String CHARACTER = 'character';
const String RIGID = 'rigid';
const String VEHICLE = 'vehicle';
const String TRIGGER = 'trigger';

const List<String> OMI_PHYSICS_BODY_MEMBERS = <String>[
TYPE,
MASS,
LINEAR_VELOCITY,
ANGULAR_VELOCITY,
INERTIA_TENSOR
];

const List<String> OMI_PHYSICS_BODY_TYPES = <String>[
STATIC,
KINEMATIC,
CHARACTER,
RIGID,
VEHICLE,
TRIGGER
];

class OmiPhysicsBody extends GltfProperty {
final String type;
final double mass;
final List<double> linearVelocity;
final List<double> angularVelocity;
final List<double> inertiaTensor;

OmiPhysicsBody._(this.type, this.mass, this.linearVelocity,
this.angularVelocity, this.inertiaTensor,
Map<String, Object> extensions, Object extras)
: super(extensions, extras);

static OmiPhysicsBody fromMap(Map<String, Object> map, Context context) {
if (context.validate) {
checkMembers(map, OMI_PHYSICS_BODY_MEMBERS, context);
}

final type = getString(map, TYPE, context,
list: OMI_PHYSICS_BODY_TYPES, req: true);

final mass = getFloat(map, MASS, context, def: 1);

final linearVelocity = getFloatList(map, LINEAR_VELOCITY, context,
lengthsList: const [3], def: const [0.0, 0.0, 0.0]);

final angularVelocity = getFloatList(map, ANGULAR_VELOCITY, context,
lengthsList: const [3], def: const [0.0, 0.0, 0.0]);

final inertiaTensor = getFloatList(map, INERTIA_TENSOR, context,
lengthsList: const [9], def: const
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]);

return OmiPhysicsBody._(
type,
mass,
linearVelocity,
angularVelocity,
inertiaTensor,
getExtensions(map, OmiPhysicsBody, context),
getExtras(map, context));
}

@override
void link(Gltf gltf, Context context) {
if (!context.validate) {
return;
}
// Get the glTF node that this physics body is attached to.
final path = context.path;
if (path.length < 2 || path[0] != 'nodes') {
return;
}
final nodeIndex = int.tryParse(path[1]);
if (nodeIndex == null) {
return;
}
final node = gltf.nodes[nodeIndex];
// Ensure that the physics body is not on the same node as a mesh or camera.
if (node.mesh != null) {
context.addIssue(SemanticError.sharesNodeWith,
args: ['A physics body', 'a mesh']);
}
if (node.camera != null) {
context.addIssue(SemanticError.sharesNodeWith,
args: ['A physics body', 'a camera']);
}
if (node.extensions.containsKey('OMI_collider')) {
context.addIssue(SemanticError.sharesNodeWith,
args: ['A physics body', 'a collider', 'collider']);
}
// Check that the physics body has at least one collider.
var hasCollider = false;
if (node.children != null) {
for (final child in node.children) {
if (child.extensions != null &&
child.extensions.containsKey(OMI_COLLIDER)) {
hasCollider = true;
break;
}
}
}
if (!hasCollider) {
context.addIssue(SemanticError.omiPhysicsBodyMissingCollider,
name: OMI_PHYSICS_BODY);
}
// Ensure that the inertia tensor is a symmetric matrix.
if (inertiaTensor[1] != inertiaTensor[3] ||
inertiaTensor[2] != inertiaTensor[6] ||
inertiaTensor[5] != inertiaTensor[7]) {
context.addIssue(SemanticError.omiPhysicsBodyInvalidInertiaTensor,
name: INERTIA_TENSOR);
}
}
}

const Extension omiPhysicsBodyExtension = Extension(
OMI_PHYSICS_BODY, <Type, ExtensionDescriptor>{
Node: ExtensionDescriptor(OmiPhysicsBody.fromMap)
});
5 changes: 4 additions & 1 deletion lib/src/ext/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import 'package:gltf/src/ext/KHR_materials_volume/khr_materials_volume.dart';
import 'package:gltf/src/ext/KHR_mesh_quantization/khr_mesh_quantization.dart';
import 'package:gltf/src/ext/KHR_texture_transform/khr_texture_transform.dart';
import 'package:gltf/src/ext/OMI_collider/omi_collider.dart';
import 'package:gltf/src/ext/OMI_physics_body/omi_physics_body.dart';
import 'package:gltf/src/hash.dart';
import 'package:meta/meta.dart';

Expand All @@ -53,6 +54,7 @@ export 'package:gltf/src/ext/KHR_materials_volume/khr_materials_volume.dart';
export 'package:gltf/src/ext/KHR_mesh_quantization/khr_mesh_quantization.dart';
export 'package:gltf/src/ext/KHR_texture_transform/khr_texture_transform.dart';
export 'package:gltf/src/ext/OMI_collider/omi_collider.dart';
export 'package:gltf/src/ext/OMI_physics_body/omi_physics_body.dart';

class Extension {
const Extension(this.name, this.functions,
Expand Down Expand Up @@ -114,7 +116,8 @@ const List<Extension> kDefaultExtensions = <Extension>[
khrMaterialsVolumeExtension,
khrMeshQuantizationExtension,
khrTextureTransformExtension,
omiColliderExtension
omiColliderExtension,
omiPhysicsBodyExtension
];

// https://github.com/KhronosGroup/glTF/blob/main/extensions/Prefixes.md
Expand Down

0 comments on commit f700fac

Please sign in to comment.