Skip to content
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

MSFT_CollisionPrimitives and MSFT_RigidBodies #2257

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

eoineoineoin
Copy link
Member

This adds support for specifying parameters useful for rigid body simulation.

Has been discussed in the 3D Formats WG, with iterations/discussion previously existing here: https://github.com/eoineoineoin/glTF_Physics. There was a strong desire from some stakeholders to split the rigid body extension into two, so that future extensions could take advantage of the definition of collision geometry.

Would love to use the prefix "EXT" or "KHR" prefix if suitable. Currently still working on samples and importers/exporters - current WIP implementations are linked from the readme.


| |Type|Description|
|-|-|-|
|**collider**|`object`|Create a collision shape in the physics engine for this node.|

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this meant to be an integer indexing into colliders with an accompanying node.MSFT_CollisionPrimitive.schema.json?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes; had some incorrect filenames, have renamed them and tightened up the wording on the README, so it's clearer.


| |Type|Description|
|-|-|-|
|**collisionSystems**|`[string]`|An array of arbitrary strings indicating the `system` a node is in.|
Copy link

@jmousseau jmousseau Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An array of arbitrary strings indicating the system a node is in.

Labeling nodes with arbitrary strings (henceforth called "categories") could be very useful in other contexts. For example, lightingCategories in a punctual light could selectively light certain nodes or renderCategories in a camera could selectively render certain nodes. Should we consider breaking this labeling into a separate node_categories extension so other extensions have a standard way to reference all nodes in a set?

{
  "nodes": [{
    "extensions": {
      "KHR_node_categories": {
        "categories": {
          "include": [0, 2]
        }
      }
    }
  }, {
    "extensions": {
      "KHR_node_categories": {
        "categories": {
          "exclude": [1]
        }
      }
    }
  }],
  "extensions": {
    "KHR_node_categories": {
      "categories": ["a", "b", "c", "d"]
    }
  }
}

A physics collider would only specify the collisionCategories because the node already defines its categories.

{
  "collisionCategories": {
    "include": [0]
  },
  "box": {
    "size": [0.1, 0.2, 0.3]
  }
}

I used the nested include/exclude pattern so that future extensions don't need to recreate their own include<categoriesName> and exclude<categoriesName> properties.

"extensions" : {},
"extras" : {}
},
"required": ["size"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should size be required when it has a default? Same goes for the other collider properties.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot; my inclination is to actually remove the default values. The authoring tools which create glTF files will always some sort of concrete object with a defined size, so makes more sense to be explicit here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought about this and changed my mind here; you're right, I'll remove the defaults. Rationale is that while I don't imagine a (e.g.) 1m^3 cube isn't terribly useful, the other extensions I've looked at provide default values which at least do something and providing a default doesn't stop an application from creating a cube with a scale more representative of the scale the tool is working in.

"type": "string"
}
},
"collideWithSystems": {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens in the default case, when neither collideWithSystems or notCollideWithSystems is specified?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be, treated equivalently to collideWithSystems being an empty set (i.e., it would collide with an object unless that other object has specified a collideWithSystems or a notCollideWithSystems which prohibits the collision.

This allows you to categorize an object, but without that object having an opinion on what objects it should collide with. e.g., you can have a collider which declares "I'm a collectable powerup", and then other nodes can decide if they should filter it.

"allOf": [ { "$ref": "glTFid.schema.json" } ],
"description": "The index of the physics material in the top level physicsMaterials array."
},
"collider" : {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't collider already specified in node.MSFT_CollisionPrimitives.schema.json? Or is this a different collider?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the collider used for physics simulation. MSFT_collision_primitives is explicitly broken into a separate schema to allow other use-cases; referencing the collider from the MSFT_rigid_bodies extension allows you to use different collider representations for different extensions which may have different requirements (consider a node which is both a UI widget and a physically simulated body).

Comment on lines 63 to 67
"gravityFactor" : {
"type": "number",
"description": "A multiplier applied to the scene's gravity.",
"default": 1.0
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it standard to have a gravityFactor defined for individual rigid bodies? I'm not super familiar with the physics side of things, but I would have thought gravity is set for the entire world and mass is how gravitational effects are altered for individual rigid bodies.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Godot has it, but it's a really non-important feature, and I don't know if it's a good thing to standardize since some engines may not have it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a common mistake to make, but the mass of a body has absolutely zero effect on the gravitation acceleration it experiences.

While a non-unity value of this parameter is not physically realistic (exotic, theoretical particles not withstanding :)), I see games use it very frequently. It's simple to implement and allows you do a bunch of neat things (please excuse the programmer-art in the examples below):

Here, the particles which skin the cactus have a negative gravity factor:

Cactus.mp4

It's also one of the tricks you'll need if you want to get "slow motion" objects even when the physics solver may not explicitly support it:

TimeFactor.mp4

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mass of a body has absolutely zero effect on the gravitation acceleration it experiences

Whoops, I understand my mistake. Need to brush up on my physics.

As for the gravity factor (and other features), what about creating a feature support table for current physics/game engines so that we can evaluate a feature's prevalence?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this feature is common in physics engines, I would be happy to add it to OMI's physics body spec.

},
"mass" : {
"type": "number",
"description": "The mass of the object.",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend specifying SI units for applicable properties such as mass.

"allOf": [ { "$ref": "glTFid.schema.json" } ],
"description": "The index of the joint limits in the top level physicsJointLimits array."
},
"enableCollision" : {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is enableCollision strictly necessary, or can enabling/disabling collision already be achieved with collideWithSystems and notCollideWithSystems? I worry about mechanisms for enabling/disabling collisions spread across multiple extensions/objects that may contradict each other.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it's possible to disable this collision by using a collision filter, this helps to avoid having to make a huge number of unique systems. Physics engines have this option as it's frequently desirable to author constraint systems where the constrained bodies overlap (please excuse programmer-art again):

ConstraintMatchingDemo

but allowing those objects to collide is undesirable from a behavioral perspective, as the contacts and joint are in direct conflict with each other. USD Physics also has the same option on the joint: https://graphics.pixar.com/usd/release/api/class_usd_physics_joint.html#afe0e317d588666298c89eb9b367162ed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Godot has the same setting. I agree that this good to have, the only reason OMI doesn't have it yet is because we want to make joints their own spec (haven't done this yet, but will do in the coming months).

"description" : "Parameters describing how a node's transform should be driven by physics simulation.",
"allOf" : [ { "$ref" : "glTFChildOfRootProperty.schema.json" } ],
"properties" : {
"isKinematic" : {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on adding a static rigid body, which is a kinematic body that must never move during simulation? A rigid body would then have a type with three possible values: "dynamic" (default), "kinematic", or "static"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a good idea to have those three values. From the perspective of a physics simulation, there's only two kinds of bodies:

  • Static bodies, which do not move
  • Dynamic bodies, which have mass and velocity

Kinematic bodies are a special-case of dynamic bodies, where, when solving the equations of motion, they have zero gravity factor, zero damping and infinite mass/inertia.

So, this spec philosophically mirrors that. A "naked" collider is treated as static; then, making the node a rigidBody imbues that collider with a mass and velocity and then, finally, making it kinematic gives it infinite effective virtual mass.

I'd really resist adding "staticness" to the "rigidBody" object - it makes the linearVelocity and angularVelocity properties meaningless - that whole configuration space is has no effect on a static body.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this spec philosophically mirrors that. A "naked" collider is treated as static;

Makes sense to me now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By this logic, it seems strange to allow a dynamic body, which by your definition has mass, to be specified as kinematic, which discards the mass. It's similar to a static body discarding the velocity.

My logic is that bodies should be primarily about combining together colliders, and secondarily about deciding how those colliders move around. It can be helpful to group together multiple static colliders together which would otherwise be "naked". It can also be helpful to group together multiple trigger colliders so that you can have a more complicated trigger volume as one volume instead of multiple.

As an example use case, in my company's game The Mirror, we allow the user to alter the imported data in-game as they wish, including by taking static colliders and making them rigid, so the ability to group together static colliders in one static body is very helpful for our use cases.

I don't have much else to say on this - I think I have made my point clear in several places. I've tried to avoid bringing up my specific uses to try and make a general case but at this point I feel like I have to.

EDIT: Actually I have one more use case. If we have joints, it would be helpful to say that joints only operate on bodies. Then if we want a rigid body to be jointed to a static body, we need a static body. This is different from a body jointed to a fixed point in space, because a static body can be teleported (it just can't have smooth motion simulated by the physics engine). For example, if you instance a glTF file at a place that isn't the origin, you would want the joint to move too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aaronfranke has created a great table showcasing how a type property might map to various engines: https://github.com/omigroup/gltf-extensions/tree/main/extensions/2.0/OMI_physics_body#physics-types

Personally, I think a type property would be easier to work with and more clear than the isKinematic flag.


`notCollideWithSystems` is useful for an object which should collide with everything except those listed in `notCollideWithSystems` (i.e., used to opt-out of collisions) while `collideWithSystems` is the inverse -- the collider should _not_ collide with any other collider excpet those listed in `collideWithSystems`

A node `A` will collide with node `B` if `A.collisionSystem ⊆ B.collideWithSystems && A.collisionSystem ⊄ B.notCollideWithSystems`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are collisions scoped to the glTF? In other words, with this specification alone, can two separate glTFs produce collision events? There's a concern the number of unique systems specified may exceed a reasonable count and this problem would be exacerbated in the multi-glTF case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, they shouldn't be scoped to a single file; applications load assets from multiple files and developers would expect that it should be possible to control whether two objects collide even if those objects come from different files.

An earlier version of this spec did specify the filter using a bitfield but I found that too limiting. It's not easy for non-technical artists to understand and it's not portable across different asset sources. I really want to enable the use-case where you can download an asset from an arbitrary source and at least have some confidence that the filtering will work correctly (because with this strategy, you can use strings to semantically label your intent, versus a bitfield where -say- bit 5 by itself is meaningless).

For what it's worth, we had this same discussion in the USD Physics working group and came to a very similar solution (there are some differences due to the way USD allows scene composition via layers, but the core idea is the same.)

Copy link

@jmousseau jmousseau Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I also found your response in eoineoineoin/glTF_Physics#2 (comment). I completely agree with strings over bitfields.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should the behavior be defined as if 5 glTF files each specify 20 different collision filtering system strings, and it cannot be represented in engines as bitwise anymore? Do we use bits until there are no more, and then ignore the rest of the collision filtering system strings for all future file imports?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The edge case I mentioned above still needs to be figured out. Is it undefined behavior?

@MattiaMontanari
Copy link

I was made aware of this PR by a message in one of the O3DE groups (https://lists.o3de.org/g/sig-simulation/message/3). This is a very valuable PR and I'd like to join the conversations from the O3DE perspective. Actually, my personal background is in engineering simulations (not real-time simulations) and I can see many similarties between the two extensions you have proposed with the way many engineering simulations tools "digest" rigid-bodides inputs. Sadly there is not standard in that field and I believe glTF, with its extensions, is a great candidate. If nothing else, I would like to see a PR that keeps the door open to engineering simulation extensions.

What's the best way to discuss these ideas? This PR and the PR from OMI are somewhat competing, and I wouldn't like to create a third one for O3DE... Is there a comitee/discussion were I all these ideas are being discussed?

@eoineoineoin
Copy link
Member Author

Hey Mattia,

Most of the discussion is happening across a few GitHub repositories and these pull requests. If you had any concrete ideas for what's missing for "serious" simulations, I'd love to hear them; while we have customers using our simulation for serious, applications, there may be functionality/object representations that other engines in the field might use, which I'm not aware of. For what it's worth, on a number of occasions, we've discussed MSFT_rigid_bodies with NVIDIA (who do more work in that area) and we're working to keep it interoperable with the physics extension in USD.

Eoin

@aaronfranke
Copy link
Contributor

aaronfranke commented Jun 15, 2023

@eoineoineoin After more closely reading through the MSFT extensions, I have realized something that I missed before, and I think it's actually really great.

OMI_collider was defining independent behavior, with a solid static object being the default, and isTrigger being settable to make the object a non-solid trigger. The isTrigger flag was a feature because the idea was to allow using OMI_collider by itself in case implementations did not want to have bodies.

What I missed before about MSFT_CollisionPrimitives is that it specifically "does not mandate any particular behaviour" for the collider shapes. Unlike OMI_collider, it does not say that a collision primitive by itself should be a static object. Instead, the MSFT_RigidBodies extension is the one that says that a collision primitive without a body should be static: "Otherwise the collider exists as a static object in the physics simulation which can be collided with but can not be moved". I love this, I think this is clever and completely avoids the issue of having the collision primitive / physics shape extension itself have responsibility of behavior, while also explicitly defining what an implementer of MSFT_RigidBodies should do for a standalone MSFT_CollisionPrimitives node.

I have adjusted the language in OMI_physics_shape (which replaces OMI_collider) to be similar to what you define in MSFT_CollisionPrimitives. I still like having an explicit static body, but defining that a physics shape without a body should be static is also great, and I love that we simply don't need to mandate a particular behavior for an implementation with only the shape extension, because we require that the implementation also implement the body extension.

Would you like to proceed with working together on KHR_physics_shape / EXT_physics_shape, which we merge as a Khronos standard first, and then develop MSFT_RigidBodies / OMI_physics_body on top of it?

Some notes on the remaining discrepancies:

  • I think the name should be physics shape, not collision primitives.
    • I would argue that "primitive" is good for boxes, spheres, etc, but not descriptive of mesh-based shapes like convex hulls or concave trimeshes. "Shape" should encompass all of them.
    • I think "collision" could possibly be confusing since someone might assume that it's solid (which isn't true for triggers). Using the name "physics" also gives us the option of using a KHR_physics_ prefix for all related physics extensions.
  • I still think that filtering should be a separate extension that we combine together with shapes.
    • Filtering is not related to the actual definition of the physics geometry, instead it defines behavior.
    • Filtering may have different implementations across engines (integers, strings, etc).
    • Filtering may be desired per-body, or per-collider. Godot only allows it per-body. Having it be a separate extension allows defining it in different places.
    • The edge cases of what happens with multiple glTF files define the same layer, or when the amount of filtering layers is too much for a physics engine to handle, still need to be resolved.
    • I don't think it makes to hinder an extension focused on shape definition with filtering which has so many edge cases and different implementations across engines.
    • OMI meeting: Lyuma strongly believes that users should not be required to implement a custom filtering system in order to just be able to load a simple box shape in GLTF.
  • Based on the discussion in last week's Khronos group meeting, I think we should use "convex" for convex shapes like MSFT does, not what OMI_collider has as "hull". One Khronos member was confused by OMI hull, so I think that's a strong enough reason to change it to "convex" for clarity. omigroup/gltf-extensions#172 EDIT: Done.
  • Based on the discussion in last week's Khronos group meeting, I think this document structure is the best (even though it's still not my first choice), since it has precedent with glTF cameras and glTF lights:
{
    "extensions": {
        "KHR_physics_shape": {
            "shapes": [
                {
                    "type": "box",
                    "box": { "size": [1, 1, 1] }
                }
            ]
        }
    }
}

@MattiaMontanari
Copy link

Hey Mattia,

Most of the discussion is happening across a few GitHub repositories and these pull requests. If you had any concrete ideas for what's missing for "serious" simulations, I'd love to hear them; while we have customers using our simulation for serious, applications, there may be functionality/object representations that other engines in the field might use, which I'm not aware of. For what it's worth, on a number of occasions, we've discussed MSFT_rigid_bodies with NVIDIA (who do more work in that area) and we're working to keep it interoperable with the physics extension in USD.

Eoin

Thanks, I'll keep on reading what I find on GitHub and in the Khronos Group members portal. While I do not have a concrete use case, I wish to stay up to date while developing the first use cases.
Perhaps you or @aaronfranke can point me to the Khronos group meeting? I do have membership access.

@eoineoineoin
Copy link
Member Author

@eoineoineoin After more closely reading through the MSFT extensions, I have realized something that I missed before, and I think it's actually really great.

OMI_collider was defining independent behavior, with a solid static object being the default, and isTrigger being settable to make the object a non-solid trigger. The isTrigger flag was a feature because the idea was to allow using OMI_collider by itself in case implementations did not want to have bodies.

What I missed before about MSFT_CollisionPrimitives is that it specifically "does not mandate any particular behaviour" for the collider shapes. Unlike OMI_collider, it does not say that a collision primitive by itself should be a static object. Instead, the MSFT_RigidBodies extension is the one that says that a collision primitive without a body should be static: "Otherwise the collider exists as a static object in the physics simulation which can be collided with but can not be moved". I love this, I think this is clever and completely avoids the issue of having the collision primitive / physics shape extension itself have responsibility of behavior, while also explicitly defining what an implementer of MSFT_RigidBodies should do for a standalone MSFT_CollisionPrimitives node.

Right; this is very important for the design of MSFT_collision_primitives - my own inclination was to keep the shape definitions inside MSFT_rigid_bodies, but some early feedback indicated that people wanted to be able to use those shapes for other purposes, which may or may not include different types of "physics" simulation; this means that whatever extension provides those shapes can't have any bias towards one particular use-case.

Would you like to proceed with working together on KHR_physics_shape / EXT_physics_shape, which we merge as a Khronos standard first, and then develop MSFT_RigidBodies / OMI_physics_body on top of it?

It might be getting too far ahead of ourselves to propose an extension which does nothing by itself, and has no users, so I'd be inclined to keep the two bundled together, until we're confident that both are finished. In principle, yes, I'd be open to synchronizing the shapes extension - I can make the same "type" change here; I also also want to add cones and tapered capsules and investigate some additional flexibility for configuring the shapes.

* I think the name should be physics shape, not collision primitives.

The issue is that "physics" is a very broad domain. MSFT_rigid_bodies and OMI_physics_body are both very explicitly concerned with "rigid body" simulations (so those should have "rigid body" in the name, at least) and calling the shape extension "physics" is overstepping a boundary and implying utility in situations that it might have none, while, at the same time, suggesting it doesn't have utility for non-physics use-cases.

I don't have a better suggestion for a name; although these shapes could be used for rendering, I don't want to suggest that they should be (and doing so would open a whole can of worms around geometry, tesselation, UVs, etc.)

For filtering, we put the options in MSFT_collision_primitives because filtering is directly related to what pairs of geometries you run collision detection on. It seemed more useful to put filtering into the shared extension, so that (e.g.) a soft body simulation extension or a "3D UI" extension could use it, without having to redefine essentially the same behaviour.

I'm open to moving the filtering into the rigid body spec, but don't think it should be a third (or fourth!) extension. Filtering, joints and bodies are all going to be handled by the rigid body simulation engine. Splitting up functionality only causes fragmentation and confusion; I think it's much better to have a single, flexible extension which covers all the use-cases one might have, and leave it up to the particular implementations to transform the data into something which is suitable for that application - the extension doesn't care that the internal representation of a filter might be a bitfield or a string - at the end of the day, filtering comes down to a "should these two objects perform collision detection" function, which returns a boolean; as long as the implementation performs some transformation which is conceptually similar, it's fine.

@aaronfranke
Copy link
Contributor

aaronfranke commented Jun 19, 2023

It might be getting too far ahead of ourselves to propose an extension which does nothing by itself, and has no users

I totally get your argument but I disagree, even if it has no users within KHR extensions it still would have uses outside of KHR extensions. I think having one canonical place to define glTF physics geometry would be helpful. Small note, we are not the only ones working on glTF specs who would find this useful: Maxar and Ultra and Blender and Panda.

I also also want to add cones and tapered capsules and investigate some additional flexibility for configuring the shapes.

To me this is out-of-scope, I would expect such shapes to be handled with another extension.

{
    "extensions": {
        "KHR_physics_shape": {
            "shapes": [
                {
                    "type": "convex",
                    "convex": { "mesh": 0 },
                    "extensions": {
                        "MSFT_fancy_shapes": {
                            "type": "cone",
                            "cone": { "radius": 1.0, "height": 1.0 }
                        }
                    }
                }
            ]
        }
    }
}

The issue is that "physics" is a very broad domain. MSFT_rigid_bodies and OMI_physics_body are both very explicitly concerned with "rigid body" simulations

Static bodies, kinematic bodies, trigger bodies, and character bodies are not rigid bodies. To be clear, they are technically "rigid" in the literal meaning of the word, in that they cannot be squished (they are not soft bodies), but the game industry has adopted "rigid" to mean a body that moves around with forces.

Filtering, joints and bodies are all going to be handled by the rigid body simulation engine.

Yes, but please do not confuse these things being handled by the physics engine with these other things:

  • All physics implementations handling filtering and joints (some may not have those features).
  • All physics implementations handling filtering and joints in the same way (some may do it differently).
  • An importer importing bodies needing to import filtering and joints at the same time (it can be separate code).
  • Filtering, joints, and bodies being conceptually the same things (they're not).

Which is why I think filtering and joints should be in a different extension.

@aaronfranke
Copy link
Contributor

For filtering, this edge case still needs to have the behavior defined explicitly.

@eoineoineoin
Copy link
Member Author

eoineoineoin commented Jul 10, 2023

The issue is that "physics" is a very broad domain. MSFT_rigid_bodies and OMI_physics_body are both very explicitly concerned with "rigid body" simulations

Static bodies, kinematic bodies, trigger bodies, and character bodies are not rigid bodies. To be clear, they are technically "rigid" in the literal meaning of the word, in that they cannot be squished (they are not soft bodies), but the game industry has adopted "rigid" to mean a body that moves around with forces.

This is absolutely not true. A rigid body is a body whose shape does not change. It is totally inappropriate for a specification to redefine well-known, widely-used terms, as that's guaranteed to cause confusion. We saw this earlier when you revealed that you were using a non-standard definition of "kinematic." A specification needs to stick to the well-established definitions -- even if you did document that you were using non-standard definitions, it's a "clever trick" that's just going to cause problems and confusion while making it much harder for anyone to understand what you're saying.

@aaronfranke
Copy link
Contributor

aaronfranke commented Jul 10, 2023

Rigid body is the industry term used for a physics body which follows rigid body dynamics:

In the physical science of dynamics, rigid-body dynamics studies the movement of systems of interconnected bodies under the action of external forces.

Please see the discussion here godotengine/godot-proposals#5183

Using any other name than RigidBody is just plain inaccurate. Rigid body is not just an industry-standard name for a physics body that emulates rigid body dynamics, it is the term used in kinematics.

Godot considered renaming RigidBody to RigidDynamicBody, and it did, but this was undone before release because users found RigidDynamicBody to be unnecessary/confusing. When users say things like "there are no other types of 'rigid' or 'dynamic' bodies" that's because they understand a 'rigid' body to be a dynamically simulated one. If the industry used rigid to mean non-squishable, this situation would not be happening.

If "rigid" is really a confusing term, then perhaps we should avoid it entirely, having a "physics body" spec with type "dynamic" as opposed to a "rigid body" spec or a "physics body" spec with type "rigid". Unreal does this by having a "physics body" with type "simulated".

@eoineoineoin
Copy link
Member Author

Rigid body is the industry term used for a physics body which follows rigid body dynamics:

In the physical science of dynamics, rigid-body dynamics studies the movement of systems of interconnected bodies under the action of external forces.

No. A rigid body is a body whose shape does not change. Literally the second sentence of the paragraph you're quoting from states this:

In the physical science of dynamics, rigid-body dynamics studies the movement of systems of interconnected bodies under the action of external forces. The assumption that the bodies are rigid (i.e. they do not deform under the action of applied forces) simplifies analysis, by reducing the parameters that describe the configuration of the system to the translation and rotation of reference frames attached to each body.[1][2] This excludes bodies that display fluid, highly elastic, and plastic behavior.

You might consider that a better resource for the definition of a rigid body would be the actual page for rigid body:

In physics, a rigid body, also known as a rigid object,[2] is a solid body in which deformation is zero or negligible. The distance between any two given points on a rigid body remains constant in time regardless of external forces or moments exerted on it. A rigid body is usually considered as a continuous distribution of mass.

That should clear things up for you. Throughout our discussions, you've made a large number of basic errors and I'm genuinely trying to fix your misconceptions here -- I don't know why you're fighting me on any of these. If someone proposes an extension for $x, other people will make an assumption that the proposer has some experience in $x. If you repeatedly make incorrect statements about $x and then refuse to acknowledge corrections, you're propagating false information, misleading those people who trusted you, and actively harming discussion.

@aaronfranke
Copy link
Contributor

aaronfranke commented Jul 25, 2023

Ok then, we can use the term "rigid" for this. And with the recent good change to the MSFT specs to have "motion" inside of "MSFT_rigid_bodies", instead of "rigidBody" inside of "MSFT_rigid_bodies", the terminology is now consistent, so I'm good with that (btw, still needs to be pushed to this PR). It's OK if "rigid" in glTF doesn't exactly match "rigid" in Godot.

If someone proposes an extension for $x, other people will make an assumption that the proposer has some experience in $x. If you repeatedly make incorrect statements about $x

I'm a programmer, not a physicist. My experiences and statements are made relative to the way I understand physics to be implemented in game engines. The standards we build in glTF simply must take portability in game engines into account, it's not up to us to invent an idealized form of physics. But naming is a minor issue relative to the other issues, things like filtering being per-collider is a much bigger issue.

@Shinmera
Copy link

Shinmera commented Nov 10, 2023

I've been looking at implementing this for my own engine, but I'm seeing one major problem with the way it is described currently (the same issues exist with #2258): there's no way to specify a transform for the physics shape itself, or compose a node's collider out of multiple physics shapes.

This is important to be able to do, since a mesh as authored could very well require an offset or different orientation to the shape to ensure a correct fit, or even require composing out of multiple primitives. Eg: a cross shape would be ideally represented by two box primitives. Using a convex hull would be grossly oversimplifying and less performant, and using a general trimesh even more so.

As it stands, to create the transform one would have to add a sub-node to store the physics shape in, but that would make it impossible for an engine to transparently determine that the node is only used for the purposes of offsetting the shape and the rigidbody properties should actually apply to the parent. Composing out of multiple shapes would be even more fraught with issues, since the author would have to separate out inertia tensors and mass, and the engine would have to recompose them.

I suggest two changes:

  1. Add a transform matrix or rotation/offset property to the base shape
  2. Turn the shape property on the node into a shapes array

@aaronfranke
Copy link
Contributor

@Shinmera You should use multiple glTF nodes to specify multiple shapes and specify their transforms. This is the typical way things are done in glTF, you can't have multiple meshes one one glTF node for example.

Trying to introduce a transform onto the shape would just be reinventing the wheel for no good reason. We already have a way to specify objects with transforms and can have extensions like shapes attached: they're called nodes.

Similarly, creating compound shapes is done with child nodes. Trying to put multiple shapes on one node would be circumventing the node system for no good reason.

As it stands, to create the transform one would have to add a sub-node to store the physics shape in, but that would make it impossible for an engine to transparently determine that the node is only used for the purposes of offsetting the shape and the rigidbody properties should actually apply to the parent.

This is an implementation detail, but the expectation is that if a parent "motion" property exists, then the shape belongs to that body. When a shape is on a body, all interactions with that shape "actually apply to the parent" as you put it.

Composing out of multiple shapes would be even more fraught with issues, since the author would have to separate out inertia tensors and mass, and the engine would have to recompose them.

There is only one inertia tensor and mass per body, just as there is only one linear velocity and angular velocity. This extension only defines rigid body physics, rigid body in the physics sense, in which all parts of the body are unsquishable and treated as one solid rigid object. There is no separation, they are always combined.

@Shinmera
Copy link

OK, thanks for the clarification! I suppose my confusion stems from the fact that it's not explicitly noted in which way it makes sense for the node properties to be specified separately across a hierarchy:

As I understand now, it is intended for it to be possible for the collider to be specified on children, but for instance rigidbody and physicsMaterial on the parent. What are the intended semantics for when a child specifies another rigidbody or physicsMaterial? Should it somehow override the parent's? Or what exactly is meant to happen?

@aaronfranke
Copy link
Contributor

@Shinmera With the MSFT physics specs, physics materials and filtering is done only per-shape instead of per-body.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants