-
Notifications
You must be signed in to change notification settings - Fork 1
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
Replace isKinematic
with a string enum for the body type
#4
Comments
So, I think there's a couple of fundamental issues touched on here, and I'd like to justify the current state of the proposal:
There's three types; static bodies (colliders who do not have a parent with a The rationale for this is that you start with objects which don't move; then, by adding a I would resist putting a "static" parameter on the rigid body object, as it leads to ambiguity due to the existence of parameters which don't make sense for a static body - what does it mean if a body is specified as static, but also has a non-zero velocity? By making the "static" body implicit by using a "bare" collider, it avoids the issue where static bodies have properties which don't make sense and allows for freedom in the implementation. Typically, a game will have (at least) an order of magnitude more static bodies than dynamic bodies, so performance of those static bodies is a serious concern. By avoiding specifying an explicit "body" type for those objects, an implementation is free to handle them as appropriate - e.g. it might create individual bodies or it might merge multiple "static" colliders together. I genuinely think this is important as scene organization here /has a direct impact on performance and without knowing (e.g.) the broadphase implementation in use, we shouldn't prescribe any particular behaviour here, lest we accidentally dictate behaviour which is accidentally a worst-case performance scenario for some engine. While some physics simulations do have "vehicle" and "character" motion types, they seem to be stuck between being too specific and not specific enough; they don't have a solid mathematical foundation (compare with the static/dynamic/keyframed distinction) and without such a foundation, I don't think they're useful. They provide a setting which may not have an effect (or, an application-dependent effect) which is confusing for artists. Further, who is to say that the motion types for a forklift (a kind of "vehicle") is suitable for an F1 racecar (also a kind of "vehicle")? For those kinds of use-cases, you probably want to add an extension that explicitly enables the kind of functionality and parameters you want. As for
There was some discussion about this already and the prevaling opinion was to stick with "rigid body physics" versus the more generic "physics" - rationale was that there are many different kinds of physics and we wouldn't want to give a reader the impression this specification supports deformable objects (for example)
A rigid body is just a body whose shape does not change, so a kinematic body still fits the definition of rigid? A kinematic body is just a special case of a general dynamic rigid body, with infinite effective mass/inertia. |
Colliders with no parent body are mostly the same in OMI physics, except that the body property allows grouping together colliders for any usage defined by the body.
You make good points here, but I disagree. It's still useful to group together static colliders under a body so that they can be moved together (while static bodies do not have smooth motion, you can still teleport them, bypassing the physics system) and physics engines can do per-body checks instead of checking every collider shape. With explicit static bodies we provide the opportunity for files to specify things, but it would be the same behavior if an engine decided to treat all static colliders individually, so it does not complicate the situation for Unity to import them. In some engines, like Godot, all colliders are required to be a member of a body to function. This model is much simpler than "some colliders move, some don't, depending on if they have a parent body", instead we have "colliders are always a part of this body and their movement is purely determined by the body" When importing a body-less collider in Godot, we have to create a static body and add the collider as a child. In order to do this without altering the scene tree, we end up with more body nodes than necessary. If we tried to optimize this by putting all static colliders in a glTF file under the same static body parent, it would require Godot to potentially significantly alter the scene tree of the imported asset by moving all of the static collider nodes to the same place. Allowing a static body type in a glTF file allows us to optimize the case for Godot without increasing the difficulty of importing into Unity (since a static body could just be imported as an empty game object).
Since a static body by definition does not move (except for teleporting), it would not move. This would be a scenario we can define as invalid in the spec and show a warning in the validator that the velocity will not be used.
The purpose of the body is to combine colliders together and give them a purpose. If What if you want to have an L-shaped trigger volume made of two boxes? In Godot and in OMI physics, this is easy, you can have one body that combines two colliders into one trigger volume. With the current draft MSFT physics, it seems that this is not possible, and that two trigger shapes can only ever be imported separately. What if you move from one part of the L-shape to another, would a trigger detecting objects entering and existing cause events to fire even though you have not left the whole shape? Not allowing multiple colliders per trigger is a limiting design flaw IMO. For the car with headlights example, OMI handles this case perfectly fine. OMI actually provides the ability to specify a trigger on either the body or the collider, so there are actually two distinct and valid ways to implement this. One is to give the car body a child trigger collider, and the other is to give the car body a child trigger body with a trigger child. OMI supports trigger in either place to help with simple use cases and improve Unity compatibility, but if we had to pick one I would suggest that the trigger only exist on the body, not the collider.
You're mixing definitions here.
It's very confusing to talk about both rigid and kinematic at the same time with definitions from different contexts. EDIT: But the solution to the last point is to use the term "dynamic" to describe bodies that move with forces. |
EDIT: This is off-topic, I'll collapse it. Another consideration:
Where are these applied? The text seems to indicate this is per-collider, and not per-body. What if you have ten colliders on a rigid body and you want all of them to have the same collision layer and masks, do you have to apply these properties to every collider? In Godot, there are collision layers and masks, but they are on the body, not on the collider shape. If collision layers and masks are per-collider, then it's not possible to import a MSFT_physics file into Godot if that file has different layers and masks between one body's colliders. This hinders the portability of MSFT_physics. If we wanted to instead put layers and masks on the body, then it would make sense to allow a static body type. In a nutshell, my opinion is that colliders should exclusively (or almost-exclusively) define the shape of a collider, and then the body defines how its child collider shapes interact with the world (whether that be kinematics, rigid movement, layers and masks, etc). Therefore, putting these properties on the body makes the most sense to me. |
Hello, First some precision request to @eoineoineoin : I am confused, I thought a node with rigid body and collider is either dynamic or kinematic.
Regarding defining more types such as vehicle and character it looks that they are either too or not enough specific: Regarding explicitly defining static nodes, that does not prevent the importer and physic engine to optimize the way it sees fit. However, explicitly defining a body just for the static property does come with the cost of carrying all the other rigid bodies related properties that are unused in that context. For the discussion on taking out the joints part in a separate extension, that could be a discussion at the Khronos group level. My thought is that we should split and avoid having applications doing half implementation of the extension. Regarding triggers, feedback from the team was that triggers shouldn't be required to have a material but having a trigger body seems better than just trigger shapes. |
@UE-FlavienP I agree regarding triggers and filtering. EDIT: This is outdated, I'll collapse it. For the proposed character and vehicle types, note that these can just be treated as kinematic and rigid in implementations where there is no distinction. However, they do have a distinction in Godot (different node types) and Unreal ("Pawn" and "Vehicle" Physics Body Object Type as opposed to "WorldDynamic" and "PhysicsBody"). |
Hey Flavien, I can certainly improve the language in the readme around how these should be interpreted, but what I'm going for:
Correct
Correct
Nearly; a
No, you'll still want to simulate these; a rigid body without a shape is useful for adding additional DoFs to constrained systems, and, from my experience, robotics applications (and similar domains) frequently don't even perform collision detection and exclusively rely on the non-contact constraints.
I'd be concerned about adding a "triggerness" property to the |
I have updated the OP in this issue to remove character/vehicle/trigger (since the section has been renamed to "motion", which is good, I think triggerness does not make sense here anymore) and renamed "rigid" to "dynamic". |
@UE-FlavienP See this issue I opened #19 I agree that trigger bodies are a vital feature, but as far as I can see the MSFT spec allows this by defining |
Another point of comparison: https://defold.com/manuals/physics-objects/ Defold defines a |
There are several problems with this enum suggestion:
|
|
glTF describes a node hierarcy. In a node hierarchy, if you transform a node, all children of that node will also be transformed. The node hierarchy is already giving you the functionality you're describing. Adding an additional grouping of child nodes via an extension doesn't actually do anything.
This is incorrect. You need the inertia to calculate equivalent forces for external simulations as well as to specify the motion space that the body rotates in. You also need the mass properties for those kinematic bodies which can change to dynamic, which is an extremely common use-case.
Right, so, if there's only two options, a boolean is much better suited to describe the possibilities. |
Another use case of static bodies is in optimization. By grouping related collider shapes under one static body, the physics engine can perform broadphase with the whole body. Without explicit static bodies, physics implementations would have to either perform broadphase for every static shape individually, or group them automatically.
Not in a way that is convenient for the physics engine. It would have to update every shape. But if there's a static body, it can just update the body, and the positions of each shape relative to that body stays the same.
What about changing a static body to kinematic or dynamic? That seems like a similarly common use-case to changing between kinematic and dynamic. In fact, I use this very thing often in projects - Godot has a "freeze" property on dynamic rigid bodies that I use to temporarily make the body static. It would be both trivial and sensible to allow the Godot importer to import "static" bodies as frozen rigid bodies so users can make them dynamic later. But this is only possible if the file contains static bodies in the first place.
I disagree, because 1) it digs us into a hole if KHR_rigid_bodies is expanded with static in the future, and 2) "not kinematic" is not a robust way to describe dynamic bodies. Booleans are best suited when there are only two states and there are no conceivable other states. Godot has several enums with only 2 possible values. But anyway, this conversation has convinced me even moreso that we should have |
Not all physics engines can group static shapes with bodies; in the engines which do, the broadphase performance can be impacted by a huge number of things - the particular broadphase algorithm(s) in use, the number and layout of objects inside the broadphase, and the application's needs for streaming/updates will all have impacts on performance. An artist clicking a button in an unrelated tool is not the best place to decide this grouping - the physics programmer implementing the extension for a particular physics engine/application has much more information on what the best thing to here is. In that respect, the current formulation of the spec is much better for broadphase performance than what you're suggesting.
You're describing a kinematic body with zero velocity. Adding a
Two posts up, you said there should only be these options! Repeating myself, you're assuming those non-existent types are mutually exclusive - even if you did have a
Again, a static+mass doesn't add anything you don't already have with |
I want to preserve static bodies when exporting from Godot, so that when importing a file in Godot or another tool that uses static bodies, it can preserve that information. I also want to preserve static bodies when exporting from other tools and importing into Godot, if both endpoints have static bodies. It's not an extra button, this is data already present, I want to preserve it, and I believe One option would to have Godot export a static body with
What if you want to describe a frozen body that will have a specified velocity after unfreezing? What about the use case of a static body with velocity as Godot defines it? (yes this is an edge case and if this was the only concern I would dismiss this myself, but, it's a minor argument in favor of having explicit static bodies).
I think there should be 3 options. But even if we only had 2 options, there are more than 2 conceivable options, so a boolean is unsuitable. I am conceiving of static right now in this thread. Describing motion is not as trivial as flipping a light switch. Regardless of how many motion types KHR_rigid_bodies defines, there are clearly more than two possible states for a body's motion (since many engines have more than two), so a boolean is unsuitable. Actually, I would argue that for all words, if the state can't be fully described by negating that word, it should be an enum. For example |
There seems to be some confusion here. The Godot documentation you linked to is describing conceptually different phenomenon than is described by the existing linearVelocity/angularVelocity fields. In Godot, that field doesn't actually move the body; it's describing a surface velocity, which is certainly a feature supported by other physics engines. However, the formulation used by Godot is not good enough for many real use-cases. In particular, dynamic bodies are just as capable of having a surface velocity and that velocity needs to be variable across the surface of the shape, so a single vector won't do. Using the existing fields to describe this functionality would not be the wrong thing to do. So it is an error to have a static body with a velocity.
There are only two options. Either a body is kinematic and is driven by a system outside of the rigid body simulation or it is not kinematic and the rigid body simulation is driving it.
KHR_rigid_bodies is designed to be a portable spec. If you want to add Godot-specific data, that should be in a Godot-specific extension. Adding a "static" type has several downsides, which I've already highlighted:
|
I can see why you came to this conclusion, with Similarly, there is also the possibility that nothing is driving it. Blender has two separate booleans for "Dynamic" and "Animated". With them both disabled, it's static. A boolean describing "in one state A is driving, in one state B is driving" does not make sense to me, because each state has something enabled. Rapier has "Dynamic", "Fixed", and two types of "Kinematic", so likewise there is value in having one of the enum values being static / fixed.
What about the case where you want to have a body start out static, and be converted to dynamic later? Two posts up, you said "You also need the mass properties for those kinematic bodies which can change to dynamic, which is an extremely common use-case". So converting between these is a common use case we must support. You could have a body with
What you call errors, I call edge cases. They aren't possible and I want them to be possible.
It's not incompatible. You can convert between these representations easily. The difference is that with converting to
The semantics of |
Just to clear up your last few misconceptions/questions:
This is just the UI - the UI could very much be improved here, and you have to stop basing your understanding of physics on the presentation layer of different applications; this is why we saw so many mistakes in OMI_physics_body. In Blender's case, two booleans would imply that there are four options. However, if you actually look at Blender's implementation, there are, in fact, only two. Blender always creates either a kinematic body, or a non-kinematic body. Despite support for them in the physics engine it uses, it never creates a "static" body:
If you read through the document you linked to, the "two types of kinematic" are identical. The only difference is the API the programmer uses to drive the body at runtime, which is inappropriate information to put into a glTF file, as even two implementations using Rapier may prefer to use a different API.
There most certainly is something driving it. You just described that exact scenario:
So, something has decided that it is not currently moving and, in the future, will change that state. That something is driving the body.
No. This is not an edge case. Velocity is a change in position with respect to time. A static body is a body whose position does not change. So, you're allowing a file to describe a "static body with non-zero velocity" which is a contradiction, and unambiguously an error.
As well as being described in the documentation, this field is located in a structure called |
I don't see why a decision would be made to reduce the information that can be stored (isKinematic does not give the amount of information that a body type would, such as allowing multiple collision meshes to exist under a single static body) and be helpful to more DCC and game engines if we can get extra information into the format for no real extra space. Rather than later deciding that we need it and having to redo the GLTF anyway to support it. Regarding having velocity on static bodies, why wouldn't that just be defined as mutually exclusive in the specification so as to avoid any issues. |
I'm pretty sure having an |
Hello, I have been integrating an FBX importer in the past and it was a difficult task as it's an unclear format and each software implements it slightly differently. It was impossible for me to support all the FBX features cross compatible with Maya and Blender. Keeping the format as easy as possible is really important. I think that the enum with the three properties (Dynamic | Kinematic | Static) make it unequivocally simple to define a static body. Being able to define a body as |
Another argument in favor of static bodies is with triggers. If you have 5 collider shapes grouped together under one static body, and a trigger begins to overlap one or some of them, you can detect that in the trigger as the body entering the trigger volume. Without a static body, this cannot properly be done. This is not the same as detecting each shape individually, because that would result in multiple enter events. It's also not possible to just ignore events from some shapes if already overlapping others, because the glTF file would not be providing a way to determine which shapes are grouped together. You could use sibling nodes, but that's a hack. |
Hi. I'd like to join the discussion and opine on this issue. I can see the arguments for isKinematic as a bool, but reading the whole lengthy discussion, I'm still not convinced it's the best approach.
|
To re-hash the arguments already made against this proposal: Disagrees with existing formatsUSD, Collada, X3D all have functionality to describe rigid body physics. These specifications were written independently and, like KHR_physics_rigid_bodies, were written by domain experts. These formats do not have an explicit "static" body type, so the current description of KHR_physics_rigid_bodies is aligned with these already-existing formats - the proposed "static body type" diverges from expert opinion on the best way to describe static geometry. I am unaware of any engine-agnostic file-format for rigid bodies which has a "static body" type. Unnecessary:Consider the hierarchy below. Each node has a collider providing static collision geometry. This is all the paramaterization that's required for static bodies:
Allowing a node to declare a "static body" would mean that an alternate way to describe this hierarchy would be:
Or:
Or:
Or:
etc. However, all of these behave identically! If there were a "static body" type, there's now 16 ways to represent this hierarchy of shapes, all of which are functionally the same. There is no reason for a user to choose one over another. There are no additional fields or properties that are added by the "static type". This "static body type" does not add anything except additional complexity, both for the artist generating the data as well as the implementer. Without a "static body" type, there's only one way to represent this hierarchy in the file, significantly simplifying the scene description. Some physics engines do have static bodies; in those engines, choosing the best grouping of collision geometries with each static body is specific to the engine itself, as well as the particular use-case and the application. Different engines will have differing requirements for how those static bodies should be grouped, which can be affected by other properties outside of the node. e.g., in some engines, a node which is animated may need to be a unique "body" - this requirement can contradict what has been specified by the "type: static body" property on the node. An example of where this might be bad is that it's possible to describe a grouping of static bodies which gives best-case performance in one engine, and worse-case performance in a different engine. The person implementing the extension for a particular engine has the most information here and is in the best position to choose such a grouping. By not having an explicit "static body type", the implementer has the flexibility to do the right thing for their engine. Adds additional errors:By adding an additional "static body type", a "static body" object receives additional fields which do not make sense for static bodies. e.g. "angular velocity" - a "static body" with a non-zero velocity is clearly a contradiction. These additional fields would need to be checked by the glTF validator, adding complexity. However, not every asset will be validated, so having such checks in the validator makes no guarantees about assets. In this discussion, we've already seen Aaron confused about the meaning of "velocity," where he suggested that, in Godot, the combination of "static body with non-zero velocity" would be handled in a particular way. This is non-portable, and does not make sense in other engines. The current specification of KHR_physics_rigid_bodies makes it impossible to make such errors, resulting in more robust and portable assets. Can add "static bodies" by other meansFor use-cases where an artist is targeting a particular engine or extension, it's still possible to use an additional extension to describe static bodies. e.g. for Aaron's "static body with velocity" case, one might construct a node:
This structure keeps KHR_physics_rigid_bodies as portable and engine-agnostic as possible, while still allowing for non-portable engine-specific details to be handled when necessary. Use of an enum "type" explodes complexityAn enum type could be extended by future extensions; by allowing the "enum type" to be "kinematic", we end up with an explosion of types. For example, earlier iterations of the OMI_physics_body spec specified several different "types":
The latter two were non-portable, Godot-specific types. However, with such a parameterization, it's impossible to describe a "kinematic vehicle," which would necessitate a new type. Similarly, you couldn't describe an object which was both a character+vehicle, nor could you describe a kinematic character+vehicle. In order to allow users to describe these, you're required to make |
To re-hash the arguments already made in favor of this proposal Compatible with existing formatsUSD, Collada, X3D all have functionality to describe rigid body physics. The proposed Converting the other way is also simple. There is no incompatibility present. NecessaryThere are absolutely situations in which you'd want to group together colliders on a static object in a way where it does change the behavior. For example, let's say you have a moving trigger, and you want to detect static objects. Without a static motion type to define a static body, each collision shape would be detected by that trigger individually. Since this repo's proposed specs do not contain any way to have compound colliders, the only way to combine colliders is to use Preserves informationLots of game engines and physics engines, including Godot, Defold, Babylon.js, Bevy, Rapier, Jolt, and more, have explicit static motion types. Excluding static from the spec hurts the ability to use glTF as a transmission format to exchange information between game engines with a static body type, because it would be discarded. In-scopeThe ability to describe a motion type of static is absolutely within the scope of the base extension for rigid body physics. While it could be done with another extension, that is worse, because defining the motion type is inherently a part of this base spec. Any other spec adding static bodies would essentially be overriding the specs in this repo. In contrast, I would still argue that joints are out-of-scope for the base physics extension specification and should be put in their own extension, certainly they are less in-scope than static bodies. In-line with Khronos best practices
I opened an issue to discuss best practices for glTF. Type enums are the normal way to define types in glTF, Eoin's proposal to not use one is going against the grain. Cameras use Also, in the upcoming Khronos audio emitter extension, emitter types are specified to be either global or positional using Enums are clearer
Even if the enum only had 2 possible values, kinematic and dynamic, an enum is cannot be misinterpreted as easily as a boolean, is easy to evolve later, and is in-line with best practices. |
Closing as "not planned" for the reasons discussed above. |
The draft spec README currently has this
isKinematic
boolean value:boolean
However, this boolean is limiting and somewhat confusing.
It's limiting because it means there are only two body types, kinematic and non-kinematic.
It's somewhat confusing because it doesn't explicitly specify what a non-kinematic body is supposed to do. The definition of "kinematics" is the motion of bodies, so should a non-kinematic body be static and not move? No, in Unity it means that a body should have dynamic rigid motion simulated by the physics engine.
I understand why the current draft spec was designed as it is, it was probably inspired by Unity which has an
isKinematic
boolean on their Rigidbody component (link). However, we can do better, we can provide a clear and flexible API that works across many engines. The string enum that I am proposing can still be easily imported into Unity.I propose that we replace the
isKinematic
boolean with atype
string enum with the following values:"static"
,"kinematic"
,"dynamic"
."static"
would be for non-moving bodies. In Unity this means to not have a Rigidbody component."kinematic"
would map to Unity's Rigidbody withisKinematic
."dynamic"
would map to Unity's Rigidbody withoutisKinematic
.Old text:
I propose that we replace the
isKinematic
boolean with atype
string enum with the following values:"static"
,"kinematic"
,"character"
,"rigid"
,"vehicle"
,"trigger"
."static"
would be for non-moving bodies. In Unity this means to not have a Rigidbody component."kinematic"
andwould both map to Unity's Rigidbody with"character"
isKinematic
."rigid"
andwould both map to Unity's Rigidbody without"vehicle"
isKinematic
.The reason for separate"character"
and"vehicle"
types is two-fold, one is that some engines have special types for characters and vehicles (like Godot and Unreal), so this improves importing into those engines, and two is that even for engines without specialized types (like Unity), it can give games a machine-readable hint of what a body is intended to be used for."trigger"
means that all colliders that are a part of this body are intended to be used as the same trigger.OMI_physics_body
which has been thoroughly debated in the OMI group.On a related note, it would make sense to rename therigidBody
property tophysicsBody
. Even without this change, a body withisKinematic
enabled doesn't use rigid body physics anymore, so it doesn't really make sense to call it rigid. With this change, the case is stronger, since only"rigid"
and"vehicle"
bodies are bodies using rigid body physics.The text was updated successfully, but these errors were encountered: