-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
base: main
Are you sure you want to change the base?
OMI_physics_shape and OMI_physics_body #2258
Conversation
a8097eb
to
ff12570
Compare
I agree completely and made a similar comment #2257 (comment)
In my opinion, collision filtering is a critical feature. Is the concern collision filtering engine support or the implementation complexities? For the former, I see support in Bullet, Jolt, PhysX, and Unity Physics. |
@jmousseau Most engines with collision filtering use bitwise layers and masks, usually with a 32-bit integer, but there are several concerns here:
EDIT: And just to clarify, these are not insurmountable challenges, but any spec including collision filtering needs to explain in detail what's supposed to happen in these situations. |
@aaronfranke You raise valid points, for which I've replied inline below. I certainly want to avoid a scenario where collision filtering is the reason why implementations don't adopt the extension or consensus can not be reached. This outcome defeats the purpose of a standard. Although I believe filtering is a critical feature, I'm open to pursuing it as a future extension.
In my opinion, ......collision filtering is a critical feature for many applications. For example, imagine a glTF authored with two overlapping colliders that approximate the model's shape. How could I prevent them from continuously producing collision events?A feature support table with the proposed extension features (such as filtering) as rows and physics/game engines as columns may allow us to make informed decisions on each of the proposed features. Thoughts?
The specification doesn't assign semantic meaning to any string, that's left to the glTF author. Let's assume filtering is part of the extension, do you think there needs to be a set of "standard" system strings? Seems related to the number of systems concern.
Wether the specification uses numbers or strings, I think implementations should always map to their own collision system domain. For example, let's say my experience already uses the first
I had this same thought, and I don't think a perfect solution exists for this problem. There's a similar problem with the number of texture coordinates (or other primitive attributes) supported per mesh primitive, especially when texture transform extensions are used extensively. The glTF specification makes a recommendation:
The physics extension could make a similar recommendation for the number of supported systems (or, more extreme, enforce a max system count per glTF). I'm also under the impression that collision systems are scoped to each glTF, meaning collisions between two different glTF is undefined behavior. Asked for clarification in #2257 (comment) |
I'll refrain on commenting on the style here, but from a technical perspective, in addition what Jack mentioned regarding the lack of filtering, I think that excluding joints is a lost opportunity. Without them, you're limited to objects which just fall in a pile. The real world genuinely does contain objects which can be joined together in all sorts of ways. In particular, physics simulations used by the robotics research community exclusively work with constraints - it's not uncommon to see a simulation which doesn't even do collision detection. Similarly, it's important to include some kind of "physics material" property - otherwise, every object appears to be composed of the same material. The USD Physics spec includes a very similar material definition to what I've proposed in MSFT_rigid_bodies: https://graphics.pixar.com/usd/release/api/class_usd_physics_material_a_p_i.html It's also a serious mistake to exclude inertia - with the exception of 1D simulations, inertia is an intrinsic property of a moving body in exactly the same manner as mass; the two are fundamentally related. We chose a 3x3 matrix because that's the actual mathematical representation of it and the type system used by glTF makes it easier to specify a single optional property rather than a pair of properties which must either both be provided or not-provided (it's not impossible though, and if people prefer the principal axis representation, I'm not opposed to modifying MSFT_rigid_bodies to represent the inertia tensor that way). While it's true that, thanks to symmetries, you can decompose the 3x3 inertia tensor into a principal axis, it looks like Godot does not expose the inertia orientation and always assumes the non-diagonal components are zero. I can't speak for why they've done it this way (especially since the underlying physics simulation supports it), but it's possible to get the same effect by adding additional transforms to the hierarchy which would effectively convert that 3vector to a 3x3 tensor. |
@eoineoineoin I agree with you that joints and physics materials are important, but I disagree that they should be in the same spec as rigid bodies. I would prefer them to be in a different spec that is composed to on top of them. There are many physics simulations that do not require joints or physics materials, so requiring importing them in order to support importing physics bodies seems like a mistake to me. As for inertia, I think it does deserve to be a part of the rigid body spec, we just need to ensure we do it right, and to provide conversions to/from other representations of inertia. I don't know the formula to convert a 3x3 matrix inertia to a Vector3 inertia, so I don't know how to implement this in Godot Engine. EDIT: Opened a PR on OMI's repo. EDIT 2: OMI's physics body spec now includes 3x3 inertia and information of how to convert to Vector3 inertia. |
ff12570
to
21991a5
Compare
OMI has merged a change that adds an inertia tensor 3x3 matrix and I have updated this PR. The spec includes information on how to convert it for engines that implement inertia differently. We are also working on physics materials and joints. For both physics materials and joints we are having them be separate specs that can be composed together. For physics materials we have done research and decided to go with the same properties as MSFT with minor changes like renames. Joints will come later. Overall we're converging these specs together which is great. |
21991a5
to
fbddb53
Compare
Added physics joints to this PR from the PR on OMI's side: omigroup/gltf-extensions#147 They are similar to Microsoft's joints but with a few differences:
|
Can we please prioritize merging the two competing standards before pressing on? OMI has made efforts to tweak our proposed standard to incorporate MSFT suggestions. I'd like to see that flow both ways. The OMI protocol suggestion is the result of a highly collaborative discussion and effort. I am not sure how many people are contributing to the MSFT standard proposed, hopefully, more than one person, but I'd rather see us come out of this with a single shared collaborative standard than two competing ones. It comes down to this: Do we want to see the Metaverse be interoperable, or do we want to bicker over who gets credit for the standard? I'd rather merge efforts, and see this as an opportunity to garner more collaborative standards in the future. This is what the MSF is all about. |
There are a number of issues I have with the OMI rigid body specifications. Some of these are major issues which limit flexibility and correctness, while others are more minor. It seems to be that the OMI rigid body specs were derived from how the Godot 3.4 physics UI presentation layer shows users the options, rather than actually representing what physics engines are doing under the hood. In all of OMI_collider, OMI_physics_body and OMI_joint, the new extension objects have an unreasonable restriction that a node can only be a collider, rigid body, joint or a shape and cannot store any other properties simultaneously. i.e. here is a node that I might want to create; it's a node which has a mesh, physics body and a geometry:
This is a node which has some graphical representation along with a physical one, and is a perfectly reasonable object to want to create. This is explicitly forbidden by the OMI physics specifications. Instead, users must add additional nodes:
I don't know why this restriction is in the spec; the only reason I can think of is "because that's what the Godot scene tree looks like in the editor." This puts an unreasonable burden on all other users of glTF, even those not using Godot. The same restriction does not occur anywhere else in glTF - a node can be a simultaneous mesh+camera+light. Why would a rigid body be any different?
Again, this is a totally arbitrary and unnecessary restriction which seems to only exist because that's the way the Godot UI presentation layer works, is that right? This is not how people make content - here's another perfectly reasonable setup: So here, there's several nodes in a hierarchy and I want to configure it for physics simulation; I'd like to be able to put a collision shape on the
Both of these options are objectively bad - it's a whole ton of extra work for an artist and it deliberately throws away any of the benefits you get from using a scene tree - i.e., in both cases, I can now no longer update the local transform of Both of the above decisions are major design flaws and those restrictions do not exist in MSFT_rigid_bodies - a collider can associated with any node in the tree and we impose no restrictions on what properties a node can have (i.e. a node can be a mesh and have a rigid_body extension simultaneously):
Both of these constructs are not only reasonable, but also how artists actually create content in practice. However, these constructs have been forbidden by OMI_collider and OMI_physics_body. OMI_collider issuesAs above, a node with an OMI_collider cannot also be a mesh, camera, rigid body, etc. The OMI_collider object has an
The OMI_collider's
This can't be done in OMI_collider.
Why does this restriction exist? There's no reason the physics shape can't concatenate all the meshes together.
Why does this restriction exist? This breaks the "zero one infinity" rule. While I appreciate in all software (not just physics) that there are practical limits to the number of vertices in a hull (or triangles in a mesh, or children of a node or any number of things) there is no reason to write this into the spec. By example, an older version of Unity could not import glTF meshes with >=65000 triangles - the correct solution was to fix/workaround the limitation in Unity. It was not to edit the spec to say "meshes should have less than 65000 triangles in total."
Probably should read "half-extents," rather than "extents" here? Also, a cube with extents of [1, 1, 1] does not have a radius of 0.5. Finally, there's no options for collision filtering; in practice, any non-trivial usage of colliders will require collision filtering. While it's common for applications to use a dynamic collision filter which ties into the business logic of the application, it's important to have some sort of filtering which covers non-dynamic filtering use-cases. OMI_physics_bodyAs above, a node with OMI_physics_body is forbidden from also being a mesh, camera, etc. and the restriction that colliders must be immediate children is overly restrictive and prevents people from making content effectively. I'm aware that in the case of the latter, the default Godot UI does not allow you to setup content like this (which is far too limiting IMO) but I was able to trivially workaround it in the MSFT_rigid_body Godot importer - obviously, that's 18 lines of code I'd have preferred not to write, but demonstrates that there's no technical limitation here, and the Godot UI should be improved.
The default mass is 1.0, but the default inertia is [0]? Is this to be interpreted that, by default, "rigid" types can't rotate? This will cause no end of end-user confusion.
This not true. A physics body, even without collision shapes adds an additional six degrees of freedom to a simulated system.
This is absolutely the wrong thing to do. On an earlier iteration of this spec which did not include inertia, I tried to make it clear that inertia was critical to the realistic movement of a body By saying "you can ignore the orientation of the inertia tensor and when writing a glTF file, set that value to the identity rotation" you're going to get the wrong result and objects will not behave realistically. The above quote from OMI_physics_body is equivalent to writing something like:
I don't think anyone would agree that this sort behaviour should be permitted by a specification. Like the mesh limitations above, the correct thing to do is to fix those engines which do not support this functionality; the solution is not to limit all glTF users who are not using those engines. I'll also note that Godot does actually support inertia orientation -- it's just not exposed in the UI. Are there any other engines which do not "support" inertia orientation? The
What does it mean to be a vehicle? At the very minimum, there needs to be a mathematical basis for saying what effect "vehicle" has on a simulated body, which is probably impossible, given the totally diverse set of use-cases for vehicles in different domains -- an arcade-style driving game is going to have a totally different vehicle model to a serious aerodynamic simulation. It is not good enough to say "do what these engines do." For example, Godot's "VehicleBody3D" does two things:
I don't know why #2 makes the object suitable for vehicle simulation, but I suspect most people would not agree that this is appropriate. Given the fact that neither of these items are suitable for a generic vehicle simulation and this type mandates no difference in how a rigid body is handled, it should not be in the spec.
Same objections to vehicle; what does it mean mathematically for an object to be a character? Again, the use-cases are so varied (even moreso than vehicles) that I'd suggest this is impossible. It's not sufficient to say "do what Godot does." A simple example of this is in this prescribed mapping. Unreal has a "Character" prefab - why is that not suitable for OMI_rigid_body.type=character objects, and instead, you mandate "Pawn, Simulate Physics = false"? Similarly, Unity has a "CharacterController" component; why is that not suitable? Why is Godot's "CharacterRigidBody3D" more suitable for characters than other engine's out-of-the-box character functionality?
Character bodies are kinematic, so they do not have gravity applied? They can also move through static objects, due to the kinematic object's infinite mass and push dynamic objects out of the way with infinite force?
Again, same issue; what is a "trigger" and how does it differ from the other options? The description of this is particularly confusing:
So, a "trigger" body is composed of multiple colliders which also have an "isTrigger" property, but the body should ensure that the collider's setting is used? This sure seems like the OMI_rigid_body.type=trigger actually has no effect? It's exactly equivalent to an OMI_rigid_body.type=rigid?
"Static" should not be a body type; all the motion properties which come with an OMI_physics_body will be ignored, which is surely breeding grounds for user confusion -- the OMI_physics_body does not have any properties which a static body makes use of. In MSFT_rigid_bodies, static bodies are implicit, which is much more flexible and avoids addition of unnecessary extension objects. OMI_physics_joint
As with the other objects, this is overly restrictive and does not align with the rest of glTF.
Why not? Again, both of these requirements are overly-restrictive. While I appreciate that you took the bulk of the joint spec from MSFT_rigid_bodies, there was a modification made which fundamentally broke it: You replaced the two pivots with a single one. A constraint, by definition links reference frames in two distinct nodes. A single transform for the joint is not sufficient to represent a joint. I am aware that this is how a joint is configured in the Godot UI, but this is another case where the specification was derived from the options in Godot's presentation layer rather than what the physics engine actually uses -- Godot's joint implementation really does represent the constraint space as a relative transform from each body: https://github.com/godotengine/godot/blob/1d14c054a12dacdc193b589e4afb0ef319ee2aae/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h#L155 As an example for why this is the wrong thing to do, consider this scene, adapted from the OMI "simple_joint.gltf" example:
The nodes "DoorFrame" and "DoorBody" model a door on a hinge, while the node "ForceSolverErrorTerm" is used to force an error in the constraint solver. If you were to simulate this scene and attempt to save it as a glTF, no matter what you do, the joint will be incorrect. Either the position or the axis (or both) will be incorrect and can never be fixed, so the door will rotate around the wrong position and in the wrong direction - that solver error is now permanently encoded into your saved glTF file. This is a pathological case, obviously, but it's also going to happen in the general case; the solver can always have an error term (though it's usually more subtle) the exact error depends on the solver behaviour, but it's especially apparent in PGS solvers, which are commonly used for real-time simulation, including by Godot.
Why is this changed? In MSFT_rigid_bodies, a "joint" object indexes into a single object in the document-level array, and that object contains the set of limits. Not sure what this adds, as those "separated" limit sets can't generally be shared and with the strategy suggested here, you end up with duplication. Consider:
Here, the
This should be optional. Collision geometry can still impose limits which can't be described with joints. |
Also, unrelated to the spec discussion, but Aaron, all of your PRs have been force-pushed. This makes it much harder for a reviewer to see what the actual changes are and causes any inline-comments on the changes to be marked as "outdated" in the GitHub review, even if they havent' been modified. If you could refrain from force-pushing in the future, that would be great. |
The reason is simple: We want to support multiple collider shapes per body, which requires child nodes. We want to support transforming those collider shapes, which requires child nodes. Therefore we make it the only option to have child nodes, instead of having 2 different ways of adding a collider shape: on the node and on child nodes. Unity allows offsetting the center on the shape itself, but this seems to add unnecessary complexity and reinvents transforms when it's not necessary since you can just use child nodes. Similarly, meshes may want to be transformed from the physics body (since the physics body origin is the center of mass), so it makes sense to have those on child nodes. However, I won't die on this hill, if we think it is very important to allow this then we can. To be clear, I have already written the ability for the Godot implementation to import colliders placed on the same node as the body since it happened to be easy, but I don't know if that's worth standardizing when we can instead standardize having less possibilities for the implementer to worry about (just child nodes).
This is another hill I will not die on. If we allow indirect children, we can do that, we just need to be aware that it adds an additional possibility that implementations need to handle.
I agree with you, but that's not what we decided as consensus in the OMI meetings. If I was just making an extension for myself, I would replace However, the reason we decided on this course of action is that we wanted to support the use case of importers only supporting If you want to remove
Sorry, but that's just straight up wrong. There is already precedent here for what to do if you want to add more but avoid touching the type string enum. Take a look at
With your example JSON, you are only providing an extension with no fallback, which means that the shape has nothing to load as a fallback. This breaks implementations that follow Keep in mind that this was designed with the precedent of
I agree, but this was requested in the OMI meetings by Unity users to improve compatibility with Unity. If we want to change this, it would be worth defining what implementations are supposed to do. Simplify the mesh? Split it up into multiple meshes? If so, do we specify the algorithms to use for simplifying and splitting? This was all discussed in the meeting, the short-term solution pending a consensus of what else to do is to put a limit. We can change this, we just need to decide exactly what that will look like. Something like "If an engine does not support convex hull shapes with the number of vertices in the shape, it should do... (what)".
This is another case of "we weren't sure what to do so we kept things simple and portable". If we define what's supposed to happen in this case (combining the meshes together), that's perfectly valid.
Extents are already half of the size. I assumed radius was understandable but maybe it's not. This may be a terminology problem, we can reword this if it's confusing. Maybe "a cube with a size of [1, 1, 1] has a distance of 0.5 between the center of the cube and the center of each face".
I agree that collision filtering is important to have somewhere, but:
You are correct, it can still be simulated and could have a function such as by connecting to a joint. We need to update the wording to say "Physics bodies without collision shapes on them will not collide with anything".
No, this is explicitly written in the spec:
I don't think the inertia tensor should be a required part of the physics body. It's not something that most users are expected to understand, and it's unreasonable to require this to be hand-calculated if writing glTF JSON by hand.
I completely disagree. It's not acceptable to say that an engine which does not support the full matrix is not allowed to have any kind of fallback. This seriously hinders portability. Keep in mind that most objects will have their parts symmetrical around the local axes, a complex inertia tensor (or even specifying one at all) is for niche use cases. I completely disagree that engines should be required to handle it, it significantly hinders implementations.
That's great - but until it's exposed, it's not suitable for the importer to touch this.
The specifics are implementation defined. The spec only requires that it behaves like a rigid body. In Godot and Unreal, there is a distinction. In Unity, there is no distinction. To me this only helps. As for Godot changing the mass to 40 kg, this is arbitrary and obviously should not be a part of the spec - importers should explicitly set the mass to whatever the file specifies, or the default of 1 kg.
I'm not an expert on Unreal, this is what I was told by Unreal users is the best equivalent type in Unreal. The character type is only required to be treated similarly to kinematic, if so then it is following the spec. Having these additional values in the enum helps implementations use a more specific type that is suitable to the intent. Again, it's implementation-specific. For example, maybe an implementation wants to look through a glTF scene for the characters and make them navigate, but it will need to not do the same with moving platforms. This is very implementation-specific, even more so than engine-specific (even in Unity you could store a flag for character when importing) but is one possible use case that I don't see a reason to forbid. Of course this is not the only way to accomplish this, there could be a separate spec or an extension, but it could be as simple as reading an additional string value.
Come on, I have no choice but to assume this was in bad faith. Of course they collide with static objects...
No, because trigger shapes under a trigger body means that the trigger shapes are combined together into one trigger, and trigger shapes under a non-trigger body means that each trigger is separate. (see below: "My view...") Quick note, the way that MSFT defines triggers as a body without a physics material is very bizarre to me. It makes no sense, it's very surprising and I would imagine that implementations may get this wrong. It's also very weird to require physics materials on all objects or else they end up being triggers, it requires all implementations to be aware of physics materials, while OMI's specs do not because whether something is a trigger is defined explicitly.
The properties like mass and inertia tensor are also usually ignored with kinematic. You could argue that the mass could be used in a niche case with kinematic, but the same argument could be applied to static (example: an object that does not move but can be deformed when something impacts it could use the mass to determine density). My view is different from yours: the primary function of a body is to combine together physics shapes. The motion of the body is secondary to that. This is what all physics types have in common, they combine shapes. The need to combine shapes together is very important. To me combining together shapes is similar to how you feel about collision filtering, it's an essential vital feature. Without being able to combine together trigger shapes with a trigger body, it is impossible to build an L-shaped trigger volume. One option would be to allow OMI_collider to combine shapes, but this is a bad idea because OMI_physics_body already has that job. Regardless, even if we only had "kinematic" and "rigid" in the enum, I still think this is more readable than MSFT's boolean. What does "not isKinematic" mean? Kinematics is the motion of bodies, so I guess this means the body should be frozen and not move. Of course I know what you mean by not having this enabled, I'm not going to make a bizzare assumption like you did with character bodies and static objects, I'm just illustrating a point.
Fundamentally, in the most simple case, what do joints connect? They connect bodies. For example, connecting 2 rigid bodies. I think it is not surprising at all and is very sensible to have connecting 2 bodies be the only case. This is another argument in favor of static bodies. Having a joint only connect bodies is the simplest way to do it. Without static bodies, if you wanted to have a joint connect to a static object, you would have to connect it to a kinematic body, or we would have to change joints to allow connecting to things that aren't a body, but that would be odd because most of the time you are connecting to a body anyway (for example, a rope hanging from the ceiling depends on the position of the ceiling, so connect it to the static body for the building).
What? Where does MSFT define 2 pivots? I can't find any mention of this in the README or the JSON schema. Physically speaking, a joint does work with a single real world physical space, and makes no preference to either body. It's also more intuitive, and is how Godot, Unreal, Roblox, and Blender expose this to the user. The way it's implemented under the hood is simply not relevant, and it seems like Unity is the odd one out here that defines the joint as a component of one rigid body that references another body.
This is not relevant, it's an implementation detail - the joint position relative to each body is always overlapping in global space when a stable simulation is saved. Therefore, we only need one position. It's neither useful nor generally portable to allow defining these separately. But again, I'm confused because MSFT doesn't do that either as far as I can see, I can't find any mention of 2 pivot points as you claim.
Joint constraints very much can be shared. For example, a default pin joint looks like this:
It's not unreasonable at all to have the joint parameters shared by many joint nodes. I feel like there is a fundamental misunderstanding here - I have tried to read the MSFT joints spec and I still do not understand, so perhaps you need to significantly reword it to be more clear and understandable.
We could change this. Godot has support for it already. I just don't know how useful or portable it is, but if we determine that it is both useful and portable then yes we should change this.
This is best practice according to the Godot documentation, to squash and force-push, it's the workflow I am used to. The history is relevant once it's merged, and you can also follow the changes over time by comparing the diffs between force-pushes, but force-pushing keeps the final history clean. But I will avoid this in the future. |
While I'd be delighted to get MSFT_rigid_bodies and OMI_physics_body more aligned (and possibly, to prefix with "EXT_",) I think there's a couple of barriers. Naming and documentation can obviously be changed pretty easily, but I think there's a number of serious gaps and mistakes in OMI_physics_body (in particular, the restrictions on document structure that OMI_physics_body imposes) which we need to close and I suspect that solving those problems in OMI_physics_body will provide a lot of clarity on the more minor issues. I'm aware we're in very different timezones, but if you want, I'm happy to jump into a call where we can diagram and throw around some ideas without having to be as rigorous as we're trying to be this discussion.
Trying to be as clear as possible; in my forklift example from the previous comment, that's really how people make content. Requiring people to restructure their content because it's "unnecessary complexity" is bad. I also fail to see how this is complex -- the collider is always added to the body with the transform of (worldFromRigidBodyNode^-1 * worldFromColliderNode). MSFT_rigid_bodies can describe the following scenarios: A node which is renderable, movable and collidable:
A node which has direct-child colliders
A node which has indirect-child colliders:
These are all important use-cases which reflect how content creators actually want to create and structure their assets. Of these, OMI_physics_body only supports the second, and even then, requires an additional node to draw the mesh:
As an example of why this is particularly bad; consider that "ColliderA" and "ColliderB" describe the collision volume of "RenderGeom" - this document structure disconnects that logical relationship. If the transform of "RenderGeom" changes, you now also have to update the transform of "ColliderA" and "ColliderB" - something which wouldn't have had to be done if the colliders were children of the mesh. However, the document layout proposed by OMI_physics_body also has an additional problem in that the use of OMI_collider is ambiguous. If another extension wants to make use of OMI_collider (which we do want to enable), with the layout proposed by OMI_physics_body, it's impossible to discern if "SomeCollider" should be used by "OMI_physics_body" or "MY_new_extension_which_uses_OMI_collider" (or both? or neither?):
MSFT_rigid_bodies does not have this problem; the collider is referenced directly by the MSFT_rigid_bodies object, rather than being implicitly linked -- visible in the examples above. On triggers:
This is still ascribing physical properties to an extension which should not be describing physics. What does Your use-case here seems to suggest that OMI_collider is still very much a "rigid body" extension not a more general-purpose set of collision primitives? In MSFT_rigid_bodies, we split out the collision geometry into a more abstract "collision" extension by request from people who wanted to use the same primitives for other, non-physics applications. On custom shapes:
Thanks for bringing up the EXT_texture_webp example. The README has a note and some discussion of the use-case:
This use-case does not work in OMI_collider. To be clear, MSFT_collision_primitives does support the case where the "MY_SDF_Shape_Extension" is required (illustrated in my previous comment) and the case where it is optional; explicitly illustrated here, in case it wasn't obvious:
I think you underestimate how important a collision filter is. I genuinely don't think any of our customers have ever shipped a product without using a filter. Here's a very simple asset I made recently: I've got a stand, constrained (represented by the black frames) to one blade of a scissor, which in turn, is constrained to the other blade of the scissor. However, because I just need the stand to collide with -say- a table, I don't need complex collision on it, so I'll use a convex hull but the convex hull of the stand looks like this: This causes forces to be applied to the second blade of the scissor and pushes that blade out unnaturally. As an artist, my options are either "decompose the stand into a more complex set of colliders" or "add a constraint with no limits, to get it's pseudo-filtering behaviour" or "use a collision filter" -- I opted for the latter as it was the most appropriate for that use-case.
Again, I think you're underestimating the importance of this and maybe only considering trivial assets. Here's another asset; the purple box represents the calculated inertia tensor; most important to note is the orientation of that box (which is the basis formed from the eigenvectors of the inertia tensor): This box is rotated ~30 degrees from the asset, which is quite a large difference from just using the identity. I don't think chairs are a particularly nice use-case and this has implications for both how the object behaves and how to physically drive an object to a particular transform. To be clear; this is just about the wording of the document. There is no physics simulation which does not support an inertia tensor, as it's absolutely required to get correct physical behaviour. The OMI_physics_body spec as it is right now, gives implementers a free pass to throw away vital simulation information seemingly arbitrarily? While on this topic, I see you made a change to the center-of-mass definition - this seems real weird to me for a number of reasons. First, inertia and center-of-mass are both manifestations of the exact same physical phenomenon - they're intrinsically linked, so it's really weird to split them up; why is the center-of-mass provided by a node translation, while the inertia tensor is specified via a property on the OMI_physics_body? More importantly, though, this interferes with how assets are authored; while this can be hidden with tooling (to a limited degree) you won't be able to get around the fact that you can't opt out of this behaviour - either an artist or the exporter needs to calculate the COM when exporting and, when importing, you'll get an extra node with an arbitrary (from the artist's perspective) transform, which is not how artists make assets - by far the vast majority of assets are modelled with their origin at the base of the object. If you add a piece of geometry (which would change the COM,) that artist has to then move all the child nodes and then apply the inverse of that translation to the body node, in order for it to appear in the correct location in the scene. With MSFT_rigid_bodies, the COM and IT are on the same footing (inside the extension object, rather than leaking into the document structure,) they're both optional and they also permit description of infinite mass/inertia (which OMI_physics_body cannot, but is important for some use-cases). If an artist isn't using tooling which can automatically calculate the COM, they don't have to provide a COM manually and the physics simulation will calculate an appropriate one.
To be clear; "kinematic" is a term used in both physics and computer animation; note that these definitions are different from the one you've used:
So, the defining characteristic of a "kinematic" body describes one which will pass through static geometry. So, when you describe a character as "kinematic but of course collides with static objects," there's something wrong. The more important point I'm trying to make here is that without a rigorous description of what it means to be a character, you'll get as many different interpretations as there are implementors. As I highlighted, Unreal, Unity3D and Godot all have native objects to represent "characters" and they're all different and you've chosen that Godot's character is the most appropriate and that Unity3D's and Unreal's character are not correct. Why? A "character" type is not required for a rigid body specification and should not be an option here. Same with vehicles.
Here's the rationale. For a trigger, they can't make use of a material - it just does not make sense to add friction/restitution to them, as it will never have an effect, while, for non-triggers, the physics simulation needs to choose some value for friction/restitution. As it is, a trigger is defined explicitly in MSFT_rigid_bodies - a collider that has a physics material (i.e. it has attributes which describe a collision response) is not a trigger, while a collider which lacks those attributes is a trigger. I think this makes sense, however, how does something like this look? I think It's a little bit awkward, in that it introduces a new object, but maybe feels less weird to you?
From the README:
I can certainly clarify the language around here if you find it confusing.
Both of these claims are incorrect; you need two pivots with distinct transforms in order to represent a joint. A single joint transform does not overlap in a shared reference frame, even for whatever definition of "stable simulation" you're using. I can write a proof or pull some citations from the literature, but please, please, please ask any physics experts in the OMI group about this.
Thanks. Changes can still be squashed on merge, but it's much handier to be able to see specific changes during a review, rather than having to dig through a large monolithic change. |
I have opened a PR to start the discussion to change this: omigroup/gltf-extensions#169 I am still skeptical of the portability of having indirect children, but I think it would make sense to allow it and just recommend direct children for those desiring a simple document structure. You are 100% correct that there is no conceptual reason for why it can't be allowed, it's just a matter of implementation.
Again, the consensus of the discussion was that people desire to have
...yes it does. If your glTF document requires an extension, then it can only be imported by implementations that have that extension. Therefore, by requiring the extension, you are automatically requiring that there is no fallback.
If
A product is much bigger than a single asset. Single assets might not require collision filtering. In fact, many games may not require collision filtering, such as countless indie or game jam games. I don't think it should be a required feature baked into the physics body spec, I think it should be separate.
Your example has 2 objects in it. I am thinking simpler. A glTF file with only one physics object in it does not need collision filtering to work, unless it was expecting to be combined with other files, but I consider that to be niche. A similar thought goes to joints: they aren't needed for simple situations, so I think they should be a separate spec. To be clear, putting it on a separate spec is not saying that it's unimportant. It may be absolutely vital for a ton of use cases. However, it's also not needed for other use cases. Putting it on a separate spec also gives users the freedom to use an alternative spec if an application has even more specific needs.
Sorry, I don't have anything nice to say in reply to this. Maybe someone else can help explain better.
You can use any character type you want in Unity3D and Unreal. But it's not required. As long as it is some kind of physics body that is kinematic, then it's compliant. You can implement any kind of superset you want. For example, maybe an implementation wants to take characters and have them pathfind around a map - sure, why not? The point is that we can say it is a character, which benefits implementations that make the distinction. If a Unity3D implementation decides it wants to attach custom scripts to all characters, but not moving platforms - this would be helpful for that.
Sorry, I still don't understand what you mean by 2 pivots. However...
...if you are talking about the pivots relative to the participating bodies, that is already the case with OMI_physics_joint. The joint node's position relative to each body is the pivot point for that body. There are two bodies, therefore there are two pivots. If you want one of the body's pivot points to be offset from that, you can modify the However, I insist that the common case is for the pivots to overlap, and this is a niche feature that should not hinder the more common cases with a more complex representation. Being able to specify a type of joint, like a pin joint, only once, and share that definition, is very useful and very readable. All of the basic use cases I can think of involve overlapping pivots. For example, a rope has its segments connected. A rope with gaps would be very weird. From Truck Town: Why should this simple use case be any more complicated than "here are a few joint nodes that constrain linearly"? I try to follow the philosophy of "if it seems like it should be that simple, make it that simple".
This is just factually not incorrect. This is how these game engines expose the behavior in the form of objects, which is also the layer with which importers and exporters will work, because we are creating objects, or creating from them. |
@eoineoineoin I apologize for the confusion before, I have discussed this with many more people and now I understand the confusion. There are two competing, but not conflicting, ideas about what a kinematic body is:
Our conflict came from me only thinking of idea 2 and you only thinking of idea 1. Ask any Godot Engine user, and they will very strongly answer with idea 2, and would be completely taken off guard by the statement "kinematic body [...] will pass through static geometry". Ask a Unity user or an animator, and they will likely answer with idea 1, since in Unity the idea 2 behavior is achieved by attaching an additional component. Furthermore, idea 1 is farther from a rigid body than idea 2, since idea 2 is meant for objects that may still behave the laws of physics like not passing through geometry, but has finer control than a rigid body, and idea 1 is for things like moving platforms that are not expected to care about any other physical objects when they move.
So, yeah, my lack of Unity knowledge completely blew up in my face here. The
I don't see it as a rigid body specification, I see it as a physics body specification. Kinematic bodies are not rigid bodies, trigger bodies are not rigid bodies. Anyway, now that we know this, I think this actually significantly increases the importance of having a separate
Note that the body extension does not need to define further details (like these properties), that should be left to another extension since it's out-of-scope for bodies. Even without an extension with further details, users can adjust the details later post-import, the most important thing is for the right type to be defined. Having the type defined in the same extension is important because it allows importers to select the correct type of body. Otherwise, if there is no character type defined on the body extension, things get complicated. Let's assume a hypothetical character extension separated from the rigid body extension:
The TL;DR is that I consider the type to be critically important to define on the body so that the correct type of object is created, and it's fine if further adjustments of data on those types would be left to other extensions, or users modifying the objects post-import. Critical on the level of specifying if a mesh shape is convex hull or concave trimesh.
Footnotes
|
For triggers: I will break it down.
Yes, I agree with that.
Not necessarily.
I understand this, but I disagree that this is a good idea. Let me ask you this: If a body does not have a physics material, and is therefore a trigger by the MSFT definition, what should This last point I really want to emphasize:
So, a physics material is per-MSFT_RigidBodies body node, but a MSFT_CollisionPrimitives shape node can be used by itself. These things are mutually incompatible with each other. If you have a collider by itself, what values for friction/restitution should it use? I see two answers:
Is there a third possibility thing I am missing? As far as I can tell, the friction for standalone MSFT_CollisionPrimitives is undefined in these specs, so I don't even know what the correct behavior is supposed to be. |
I realize we're having a very similar conversation on two threads (and I think your opinion has changed on some of these matters) but this is something important to consider:
"triggerness" is a property of how an object responds to collision; "kinematicness" describes of the motion of the object. They are orthogonal properties. You can have a static or dynamic or kinematic trigger - they each have different use-cases and are all equally valid. Earlier, I suggested a change which would make triggers more explicit and allow for implementations to have some sort of "default" physics material - eoineoineoin@34cbe95 - have you given any thought to that? |
Technically yes, but there is no sense in having a dynamic rigid body trigger, because a trigger's defining feature is that its shapes are not solid and only are used for detection, so a trigger moving around dynamically with forces would just fall forever. A trigger does not have its motion directly determined by the physics engine, and it does not directly determine any other body's motion, it only exists in physics to detect things.
So it references only one shape for the trigger volume? This would prevent having triggers with multiple shapes, like an L-shaped trigger volume specified by 2 box shapes. |
This is wrong. Application or game code can apply forces to dynamic triggers. Joints can apply forces to dynamic triggers.
It has the exact same semantics as the "collider" property, so of course you can build L-shaped triggers, just as you can build L-shaped collision volumes. |
Well, technically yes, but I would consider that to be 2 bodies, not 1. A trigger would be added as a child of the body that is simulated. At least, this is how what you describe would have to be done in Godot to implement a dynamic trigger body.
At best, "can", not "does".
Sorry, I don't understand. It's "a" collider, how do you reference multiple? |
No. That's not 2 bodies. Adding an additional body adds six degrees of freedom, which the compound of a non-trigger and a trigger does not have. If you want to implement it that way, that's fine, but that's not what is actually being described, which is that the trigger and non-trigger colliders are both attached to the same frame.
Exactly the same way you would make a non-trigger with an L-shape. You add a child node to position two boxes relative to one another:
|
Those degrees of freedom can just not be set.
So for a solid collider, you add shapes with What you propose works but I still think it would be simpler to have a body simply be an object that takes its child shapes and combines them into a singular purpose (like static collision, kinematic body, dynamic rigid body, or trigger detection). For the edge case of wanting a trigger with dynamic physics simulated on it, to me it's perfectly fine to say this should be 2 body nodes, because you have 2 different sets of shapes, and that's what all bodies do, combine shapes. Comparing your proposal to this, you are just replacing the case of "a body can be a trigger" with "a body has a separate set of shapes for trigger", which I think is worse. By the way, yes I am biased in favor of how Godot works, but Godot works really well. We like to break compatibility often, and nobody has proposed changing how triggers work, so Godot users like how it works. It's simple and makes intuitive sense for users to have a body that combines shapes for one purpose. Also, please fix the naming inconsistencies in your spec. Is it |
@eoineoineoin Do you have any further objections to the OMI physics standards relating to anything that's impossible to do? To me this is the simplest approach that makes every desired situation possible without requiring any unnecessary information. I know you have complained about the document structure about where the shapes are allowed, we are changing that based on your feedback. I know you have complained about the extensibility of OMI_collider's shape types, but I explained how you can extend it. I know you have complained about the lack of a trigger simulated dynamically with forces, but I explained that you can use a 2nd body. I know you have complained about physics materials, joints, and filtering not being in the base spec, but that can be made possible by adding more extensions. More about the trigger definition: I want to emphasize further how much I dislike the no-material-means-trigger thing. It feels like one of those "clever" tricks that seems neat until it inevitably causes problems later on. Clever tricks should not be a design goal, in fact we should strive for the polar opposite, we should strive for making the spec as clear as possible to prevent implementations from getting it wrong. With no-material-means-trigger, I would have to write a comment in the implementation describing this behavior, because it's unexpected and surprising. We should not be surprising people, we should design the spec to match an implementer's intuitive expectations. The spec's text is there to elaborate on the details, not to go contrary to the expectations if you only read the property names. The precedent in glTF is that everything clear, simple, easy to parse, and intuitive, even if it means some redundancy (for example, camera types both having I think it speaks volumes about your MSFT physics specs that I am continually misunderstanding it and being confused, and other people that I have discussed this with are also confused. Of course the OMI specs are not immune from confusion too - for example the character type was confusing - I'm not saying that what OMI has on the table is perfect, but I consider it miles better, it's clear, concise, and it's simple as can be. While I liked this clever trick about the semantics of defining shape behavior, even that is kinda pushing it and to me that is only permissible because it's a purely semantic difference compared to the shapes saying they are solid by default. Sorry if this seems harsh - but I really need to make it clear that it's not just a minor issue, my belief is that "clever" tricks like no-material-means-trigger are fundamentally the completely wrong approach to take. |
I don't know what you mean by this. As far as I can see, the colliders and triggers are defined in exactly the same way (modulo the |
@eoineoineoin It's possible that I am misunderstanding something, your specs are unclear and in disagreement with the example files. The example files have data like this (inside "name": "LanternPole_Body",
"extensions": {
"MSFT_physics": {
"collider": {
"trimesh": {
"mesh": 0
}
}
}
} The "name": "ExampleNode",
"extensions": {
"MSFT_CollisionPrimitives": {
"collider": 0
}
}, Your example above defines a trigger shape like this (inside "name":"VerticalPartOfTheL",
"extensions":{
"MSFT_rigid_bodies":{
"trigger": { "collider": 0 }
}
}, That's 3 completely different data structures, with 3 different extension names. The top one is defining the shape locally, while the others point to a document-level array. The collider uses a |
...gravity factor, schema version, default values in schemas, list formatting, format examples, update wording to be more similar to KHR/MSFT physics, refactor joints to be more similar to KHR/MSFT physics.
This pull request adds OMI's
OMI_physics_shape
andOMI_physics_body
glTF extensions to this repo. These extensions allow specifying physics shapes and behavior for objects in a glTF file. Additionally, these extensions work together withOMI_link
andOMI_seat
to define trigger volumes for interacting with URIs and seats.This extension has been discussed in the OMI group extensively over the past year, with many design decisions made to improve the spec to be highly portable between Unity, Unreal, Godot, and more. For example, there was extensive discussion about if cylinders should be specified, and if so, what guidelines to give to approximate them for engines that do not support cylinders.
A complete import and export pipeline for both content creation and consumption is available in Godot here: godotengine/godot#69266. OMI_collider is also implemented in Third Room. Also, I made a glTF Validator implementation here: KhronosGroup/glTF-Validator#202 and this PR includes example files.
These extensions are a competing standard to Microsoft's physics #2257. OMI's concerns about this spec have been listed as separate issues on their issue tracker here. The biggest difference between the specs:
isKinematic
boolean. The boolean is less flexible, and in my opinion, is less readable even if there were only two options. The definition of "kinematics" is the motion of bodies, so should a non-kinematic body be static and not move? No, it means that a body should be simulated with rigid body dynamics. In addition to kinematic and dynamic, OMI allows defining explicit static bodies.Our hope is to hammer out the differences between the specs to find a common ground that will make everyone happy. Since Microsoft's physics now has a PR open, we wanted to put OMI's design on the table too.