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

Allow to define center of mass and inertia tensor #945

Closed
Zylann opened this issue May 28, 2020 · 9 comments
Closed

Allow to define center of mass and inertia tensor #945

Zylann opened this issue May 28, 2020 · 9 comments
Milestone

Comments

@Zylann
Copy link

Zylann commented May 28, 2020

Continuation of godotengine/godot#28062
And godotengine/godot#12353

Describe the project you are working on:
Any kind of physics-driven game, especially one where players can build. Attempted a prototype but had to stop due to lack of the feature.

Describe the problem or limitation you are having in your project:
Godot does not appear to calculate the center of mass properly, and does not have an API to choose where it is. It rather defaults it as the transform origin of the whole body, which is incredibly impractical. That works relatively well in simple cases and eventually on pre-constructed game elements, but as soon as the game allows to change the shape of the body through customization, building system or partial destruction in the middle of simulation, properly relocating the center of mass through teleportation of all its parts becomes a problem.
Inertia tensor is also something that can vary depending on the parts of the body, so I included it in this proposal.

Note: this issue is mainly about 3D, but I believe 2D has the same problem.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:
Two things:

  • Center of mass and inertia tensor should be properly computed based on the positionning and mass of its parts, if we want to. That could be a default for rigidbodies.
  • We should be able to override them, without having to shift everything around the root transform. This is useful in case some parts dynamically change in mass, get destroyed, or if you simply want something custom not following realistic dynamics.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
I believe the visual transform being confounded with the center of mass is a side-effect of Godot taking the simplest path to sync with a physics engine. Sadly, this makes physics-based games a chore to create, and that's not how other engines work. Those should really be decoupled. I worked for a while on physics-based games and in these cases the visual transform doesn't even matter, it's controlled by the simulation anyways. We can even decide where it is for other use cases. When we need to associate the body with a logical position, we know we should use the center of mass anyways, and not its visual transform, because in that case they have different uses.

I believe Bullet proposes a way to calculate center of mass and inertia tensor automatically. If not, we may provide a default implementation.

This breaks compatibility with physics-based games that worked around the COM being at transform origin, but then it can be handled easily specifically with a custom center of mass setting it just there, or by having an enum allowing to choose between ORIGIN, AUTO or CUSTOM, defaulting to ORIGIN. Although, I'd expect this only in 4.x when physics get reworked so breaking compat could be fine.

If this enhancement will not be used often, can it be worked around with a few lines of script?:
As explained you can try to teleport all the parts to align them with the body's origin. However my previous experience with teleporting parts of a body has been a nightmare, and it is well known that rigidbodies don't like having their position set like that (performance and stability issues). So I really wish it wasn't required.

Is there a reason why this should be core and not an add-on in the asset library?:
This is part of how Godot synchronizes with its physics engine, and it introduces a new property representing the offset of the center of mass. A script can't change that, unless you reprogram all physics nodes using PhysicsServer and stop using built-in ones, which is far from a few lines of code.

@Zireael07
Copy link

Yay, I was going to rewrite it but you beat me to it.
One more use case: center of mass lowering is a common trick to make Bullet physics vehicles more stable, but currently there is no way to do it.

@19PHOBOSS98

This comment has been minimized.

@Calinou
Copy link
Member

Calinou commented Sep 8, 2020

@19PHOBOSS98 Please don't bump issues without contributing significant new information. Use the 👍 reaction button on the first post instead.

@AlnisS
Copy link

AlnisS commented Apr 2, 2021

Is there any workaround for setting the inertia tensor at the moment? It's ok if it's janky or very manual.

We'd like to use Godot for a simulation of a CubeSat, including reaction wheels and the propulsion system, with an inertia tensor, mass, and center of mass derived from a CAD model. The reason why we'd like to use Godot is it would give us a very visual and interactive real-time output as well as the ability to add simulated cameras for our star tracking algorithms. Plus, it's open-source!

Thanks!

@Calinou
Copy link
Member

Calinou commented Apr 2, 2021

Is there any workaround for setting the inertia tensor at the moment? It's ok if it's janky or very manual.

As stated in OP:

If this enhancement will not be used often, can it be worked around with a few lines of script?:
As explained you can try to teleport all the parts to align them with the body's origin. However my previous experience with teleporting parts of a body has been a nightmare, and it is well known that rigidbodies don't like having their position set like that (performance and stability issues). So I really wish it wasn't required.

If you can design the meshes manually (or generate them procedurally), you could also move their origin to be far away from the center in the 3D DCC. However, this can't be done in real-time.

@AlnisS
Copy link

AlnisS commented Apr 2, 2021

Ah, I should have clarified, sorry!

From my understanding, the workaround in the OP would let you adjust the center of mass, but Godot would still calculate the inertia tensor internally based on the positions of the colliders relative to the new center of mass/transform origin.

This gets around having to set the inertia tensor for many use cases (such as knocking parts off of structures/spacecraft/etc. and having a center of mass that is not at the original transform origin point), but from what I understand, does not let you put in a numerical 3x3 matrix for the inertia tensor. The challenge here isn't so much the center of mass vs the origin point, but rather setting the inertia tensor to match the CAD model (instead of Godot's auto-calculated inertia tensor from the collider positions).

Thank you for the advice in any case!

@Wolfe2x7
Copy link

Wolfe2x7 commented Apr 12, 2021

Is there any workaround for setting the inertia tensor at the moment? It's ok if it's janky or very manual.

In my project I am using an extra RigidBody to manipulate the distribution of mass -- an invisible shape that does not collide with anything (enabled, but with nothing for collision layers/masks), pinned to the main body at the origin with the linear limits of a Generic6DOFJoint.

By attaching a long cylinder along the Z basis, I can alter the moment of inertia around the Y and X axes. You can get a very strong effect from making the shape very large or heavy, and if you affix it at the origin you can still control the center of mass. :)

@AlnisS
Copy link

AlnisS commented Apr 19, 2021

@Wolfe2x7 That's an interesting workaround! Thank you for sharing! I'll have to play around with it to see if I can find some scriptable way of setting the inertia tensor using this approach (i.e. without having to move/tweak things, check the value, move/tweak things, check the value...). Thanks for the help!

Ideally, we would have some way of setting these values directly (or setting an equivalent representation like Unity does with setting diagonal entries & a quaternion representing the rotation of the axes of the principal moments of inertia relative to the body's orientation)

@pouleyKetchoupp
Copy link

Closed with godotengine/godot#49610

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

No branches or pull requests

7 participants