godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.39k stars 20.02k forks source link

Generic6DOFJoint3D Motors and Springs not working #66335

Open ellogwen opened 1 year ago

ellogwen commented 1 year ago

Godot version

4.0 Beta 1

System information

Linux (but it doesn't matter)

Issue description

First I thought it was a bug, since I didn't get the motors and springs of the Generic6DOFJoint3D to work, after I looked up the source code https://github.com/godotengine/godot/blob/bcf754d735249a779469839455d925cf42b48057/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp I saw that it was just not implemented.

Will this be available in the final 4 release or is 3D physics not in scope yet?

Steps to reproduce

Add a Generic6DOFJoint3D, setup motors or springs, see them do nothing

Minimal reproduction project

No response

Calinou commented 1 year ago

Will this be available in the final 4 release or is 3D physics not in scope yet?

We don't know if this will be implemented in time for 4.0, as there are few physics contributors.

Rinocrosser commented 1 year ago

@Calinou

If you can't fix it, can you rollback to Bullet physics? Also my issue seems to be the same as this one:

https://github.com/godotengine/godot/issues/68852

akien-mga commented 1 year ago

See #68852 for a MRP for angular motor.

Rinocrosser commented 1 year ago

And from #68852 limiters also won't work properly (on Hinge 3D as well), if the motor is enabled and limiters values aren't 0-0.

Rinocrosser commented 1 year ago

@akien-mga Any plans for 4.1?

akien-mga commented 1 year ago

Nobody is working on this specifically right now, so I can't make any promise. Any interested contributor is welcome to have a go at implementing this joint in GodotPhysics.

thierryreding commented 1 year ago

I've looked a bit through the code and it looks like the Godot Physics 6dof joint code is based on an early version from Bullet, so it may be possible to update it to a more recent version of that code which has the motor/spring support. I'm willing to take a stab at it, but to set expectations I'm very short on spare time, so no idea how much and how fast I can make progress. If anyone with more time would like to take this on, let me know.

Tony2371 commented 1 year ago

I've looked a bit through the code and it looks like the Godot Physics 6dof joint code is based on an early version from Bullet, so it may be possible to update it to a more recent version of that code which has the motor/spring support. I'm willing to take a stab at it, but to set expectations I'm very short on spare time, so no idea how much and how fast I can make progress. If anyone with more time would like to take this on, let me know.

Hello, mate! Did you manage to advance somehow in resolving this issue?

thierryreding commented 1 year ago

Not really. Turns out this isn't as simple as updating the code to a more recent version from Bullet. The Bullet module in Godot 3.5 uses a variant of the 6dof joint that has significantly changed since the version that Godot Physics forked from a long time ago. The existing Godot Physics 6dof joint also has a couple of oddities that make it behave completely differently from the version in 3.5. For example, if you constrain the Y axis to upper and lower limits of 0 (meaning that it shouldn't move at all on the Y axis), I still see it move down a little bit (about 0.2 units over the first half a second or so) under the influence of gravity.

So after a bit of investigation I tried to incrementally improve the existing code, but given the time constraints I made very little progress. I managed to implement a linear motor that seems to work to some degree, though, again, it behaves slightly differently from Godot 3.5. I also experimented a bit with the linear spring component, but haven't managed to get something that behaves in a stable way (i.e. depending on the stiffness/damping, it can oscillate completely out of control).

I tried to read up a bit on motors/springs and physics solvers in general, but the time constraints make this progress really slow. My tentative plan is to look at angular motors/springs next, which is what I originally wanted to have for an idea that I wanted to play around with (I started with linear because I thought it'd be simpler...). There's a lot of commonality between linear and angular motors/springs, at least in the Bullet code, so progress on any of those should impact the other as well.

I also looked around various other physics engines for inspiration, but they all work in slightly different ways and I wanted to keep as close to the behavior of Godot 3.5 as possible, to make migration to Godot 4 more seamless. Which brings me to another thing that I've been pondering: if we want Godot 4 to behave as closely as possible to Godot 3.5, maybe it'd be better to forward-port the Bullet module rather than essentially duplicating Bullet's code in Godot. I understand that there's been a plan for that anyway, so perhaps for the 6dof joint in particular that'd be easier. I've played around with some of the other joints and they seem to work fairly well, as do unconstrained physics.

The code is a bit messy right now, but I'll try to clean things up a bit and upload what I have if anybody wants to give this a go. One thing that would be nice to have is a collection of small demos that use 6dof joints. So far I've been creating use-cases myself, but that's obviously very biased and also time-consuming.

Tony2371 commented 1 year ago

Not really. Turns out this isn't as simple as updating the code to a more recent version from Bullet. The Bullet module in Godot 3.5 uses a variant of the 6dof joint that has significantly changed since the version that Godot Physics forked from a long time ago. The existing Godot Physics 6dof joint also has a couple of oddities that make it behave completely differently from the version in 3.5. For example, if you constrain the Y axis to upper and lower limits of 0 (meaning that it shouldn't move at all on the Y axis), I still see it move down a little bit (about 0.2 units over the first half a second or so) under the influence of gravity.

So after a bit of investigation I tried to incrementally improve the existing code, but given the time constraints I made very little progress. I managed to implement a linear motor that seems to work to some degree, though, again, it behaves slightly differently from Godot 3.5. I also experimented a bit with the linear spring component, but haven't managed to get something that behaves in a stable way (i.e. depending on the stiffness/damping, it can oscillate completely out of control).

I tried to read up a bit on motors/springs and physics solvers in general, but the time constraints make this progress really slow. My tentative plan is to look at angular motors/springs next, which is what I originally wanted to have for an idea that I wanted to play around with (I started with linear because I thought it'd be simpler...). There's a lot of commonality between linear and angular motors/springs, at least in the Bullet code, so progress on any of those should impact the other as well.

I also looked around various other physics engines for inspiration, but they all work in slightly different ways and I wanted to keep as close to the behavior of Godot 3.5 as possible, to make migration to Godot 4 more seamless. Which brings me to another thing that I've been pondering: if we want Godot 4 to behave as closely as possible to Godot 3.5, maybe it'd be better to forward-port the Bullet module rather than essentially duplicating Bullet's code in Godot. I understand that there's been a plan for that anyway, so perhaps for the 6dof joint in particular that'd be easier. I've played around with some of the other joints and they seem to work fairly well, as do unconstrained physics.

The code is a bit messy right now, but I'll try to clean things up a bit and upload what I have if anybody wants to give this a go. One thing that would be nice to have is a collection of small demos that use 6dof joints. So far I've been creating use-cases myself, but that's obviously very biased and also time-consuming.

Actually you have already advanced a lot! I hope there will be some kind of solution any time soon

thierryreding commented 1 year ago

I've uploaded a branch that has working linear and angular motors implemented (the angular motors are mostly based on the Hinge Joint code):

https://github.com/thierryreding/godot/tree/6dof

The history isn't cleaned up on purpose, for my own reference. I'll clean it up eventually. Next up will be springs, but based on some experiments I've been doing I'm not overly confident that I can make them work. There's also potential to clean up some of the existing code. Feel free to give this a try. I've also uploaded the demo project I use to test these:

https://github.com/thierryreding/godot-physics

markusneg commented 1 year ago

Tested your code with non-zero linear limits and motor enabled and it seems to work. I noticed that opposing motor forces lead to body movement although being identical. But maybe that has nothing to do with your specific code. Also, motor velocities behave odd (out of scale, increasing velocity parameters sometimes result in lower velocities).

alex-karev commented 1 year ago

For anyone interested in springs, I've just discovered a good video on YouTube explaining how to make Active Ragdolls in Godot 4.0

The author also has this repo with an example project featuring Active Ragdolls.

It can be helpful for developers who want to implement angular springs in their Godot 4 project themselves as a workaround, or for engine contributors working on adding this feature to the Godot Physics Engine.

AttackButton commented 11 months ago

Yeah, it is fixed by the Jolt Physics. : )

6dof_test

It is missing a script in the mrp to test this, so:


extends Node3D

func _physics_process(delta: float) -> void:
    $Generic6DOFJoint3D3.set_param_x(Generic6DOFJoint3D.PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, -8)
    $Generic6DOFJoint3D2.set_param_x(Generic6DOFJoint3D.PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, -8)
    $Generic6DOFJoint3D.set_param_x(Generic6DOFJoint3D.PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, -8)
    $Generic6DOFJoint3D4.set_param_x(Generic6DOFJoint3D.PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, -8)
Rinocrosser commented 11 months ago

Yeah, it is fixed by the Jolt Physics. : )

6dof_test 6dof_test

It is missing a script in the mrp to test this, so:


extends Node3D

func _physics_process(delta: float) -> void:
  $Generic6DOFJoint3D3.set_param_x(Generic6DOFJoint3D.PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, -8)
  $Generic6DOFJoint3D2.set_param_x(Generic6DOFJoint3D.PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, -8)
  $Generic6DOFJoint3D.set_param_x(Generic6DOFJoint3D.PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, -8)
  $Generic6DOFJoint3D4.set_param_x(Generic6DOFJoint3D.PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, -8)

In my demo, the motion was set in node settings (not script)

But thanks a lot anyway! Jolt should become the default option!

GrauBlitz commented 11 months ago

But thanks a lot anyway! Jolt should become the default option!

At least it should be included inside the engine, not as external addon. I miss Bullet too much...

Calinou commented 11 months ago

At least it should be included inside the engine, not as external addon. I miss Bullet too much...

See https://github.com/godotengine/godot-proposals/issues/7308.