Skip to content

Add ability to apply forces and impulses to SoftBody3D #100463

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

Merged

Conversation

PiCode9560
Copy link
Contributor

@PiCode9560 PiCode9560 commented Dec 16, 2024

Closes godotengine/godot-proposals#1013

The goal of this PR is to add apply_impulse and apply_force to the Softbody node

Adding them to the GodotPhysics and JoltPhysics.

Added functions

Softbody3D:
void apply_central_force(force: Vector3)
void apply_force(force: Vector3, point_index: int)
void apply_central_impulse(impulse: Vector3)
void apply_impulse(impulse: Vector3, point_index: int)

PhysicsServer3D:
void soft_body_apply_central_force(body: RID, force: Vector3)
void soft_body_apply_central_impulse(body: RID, impulse: Vector3)
void soft_body_apply_point_force(body: RID, force: Vector3, point_index: int)
void soft_body_apply_point_impulse(body: RID, impulse: Vector3, point_index: int)

Built-in documentation

Edit: I think these are a bit outdated

Show documentation

PhysicsServer3D

● void soft_body_apply_central_force(body: RID, force: Vector3)

Distributes and applies an force to all vertices. A force is time dependent and meant to be applied every physics update.

● void soft_body_apply_central_impulse(body: RID, impulse: Vector3)

Distributes and applies an impulse to all vertices.

An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).

● void soft_body_apply_point_force(body: RID, force: Vector3, point_index: int)

Applies a force to a vertex. A force is time dependent and meant to be applied every physics update.

● void soft_body_apply_point_impulse(body: RID, impulse: Vector3, point_index: int)

Applies an impulse to a vertex.

An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).

SoftBody3D

● void apply_central_force(force: Vector3)

Distributes and applies an force to all vertices. A force is time dependent and meant to be applied every physics update.

● void apply_central_impulse(impulse: Vector3)

Distributes and applies an impulse to all vertices.

An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).

● void apply_force(force: Vector3, point_index: int)

Applies a force to a vertex. A force is time dependent and meant to be applied every physics update.

● void apply_impulse(impulse: Vector3, point_index: int)

Applies an impulse to a vertex.

An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).

Demo

Demo project: godot-softbody-apply-force-and-impulse-test.zip

These are how the functions compared to rigidbody.

The impulses have a strength of 0.2.
The forces have a strength of 15.

Jolt physics:

Jolt.SoftBody.mp4

Godot physics:

Godot.SoftBody.mp4

Player Controller (Jolt physics):

softbody.controller.mp4

Implementation Details

Godot apply_impulse

GodotSoftbody3D already have apply_node_impulse method which apply impulse to a vertex. So I just use that for the softbody.apply_impulse.

Godot apply_force

GodotSoftbody3D have vertex.f which stores the applied forces, and it will handle it somewhere. Therefore, I only need to add a method that add the forces to it.

Jolt apply_impulse

JoltSoftbody3D didn't have a method to apply impulse. So I added JoltSoftBody3D::apply_node_impulse. It works like the GodotSoftBody3D::apply_node_impulse which just add impulse * vertex.inverse_mass to the vertex velocity.

Jolt apply_force

[Outdated]
I notice that the core JoltPhysics didn't have a way to apply force to softbody vertex. Hence, I have to add that functionality into the core of the JoltPhysics engine.

I added vertex.mForce, which store the forces that are going to be applied. Then applies it in the SoftBodyMotionProperties::IntegratePositions and reset the force on SoftBodyMotionProperties::UpdateSoftBodyState.

apply_central_impulse/force

For SoftBody.apply_central_impulse and SoftBody.apply_central_force I added apply_central_impulse and apply_central_force methods to jolt and godot. It works like the apply_node_impulse/force but the impulse/force is divided by the vertex count and applies it to all vertices.

@PiCode9560
Copy link
Contributor Author

PiCode9560 commented Dec 16, 2024

It's fine, right? If I add it to jolt and godotphysics in the same PR.

Edit: I'm just going to do it, I think it's fine.

@PiCode9560
Copy link
Contributor Author

apply_force added.

The Softbody class didn't have apply_force method, so I have to make it myself. I don't really know how force works. So I just tried stealing it from the GodotBody3D. Also, assuming that the GodotSoftBody3D's node.f handle the forces, this is how the force is done: node.f += p_force;
After testing it, the force looks kind of correct. So... good enough for now!

@adamscott adamscott changed the title Adding apply_impulse and apply_force to softbody Adding SoftBody3D::apply_impulse() and SoftBody3D::apply_force() Dec 16, 2024
@PiCode9560
Copy link
Contributor Author

apply_impulse added to jolt.

Most of the code from the apply_node_impulse is just copied from other methods, So I'm not 100% sure if all the error checking is necessary.

@PiCode9560
Copy link
Contributor Author

What I made with it so far:

softbody.controller.mp4

@PiCode9560
Copy link
Contributor Author

PiCode9560 commented Dec 17, 2024

Next, I'm working on adding apply_force() to jolt, but I can't figure out how to do that. If there's smart people out there want to give suggestions, you are welcome to.

Edit: Or just, @mihe HELP!

@AThousandShips AThousandShips changed the title Adding SoftBody3D::apply_impulse() and SoftBody3D::apply_force() Add SoftBody3D::apply_impulse() and SoftBody3D::apply_force() Dec 17, 2024
@PiCode9560
Copy link
Contributor Author

I think I figure it out, from comparing jolt with godot physics' GodotSoftBody3D and GodotBody3D.

What I understand is, Jolt softbody don't have the functionality to apply force. So I think I have to add the functionality to the SoftBodyMotionProperties class.

@PiCode9560
Copy link
Contributor Author

Added apply_force to jolt, but not sure if it behaves properly.

Also, I just found out that sometimes when running the scene, the softbody just disappear. IDK how that happened.

@PiCode9560
Copy link
Contributor Author

Added apply_central_force and apply_central_impulse to jolt and godot.

The way it works is just applying the force/impulse to all vertices, but the force/impulse is divided by the vertices count.

@PiCode9560
Copy link
Contributor Author

These are how the functions compared to rigidbody.

The impulses have a strength of 0.2.
The forces have a strength of 15.

Jolt physics:

softbody.jolt.mp4

Godot physics:

softbody.godot.mp4

@PiCode9560 PiCode9560 marked this pull request as ready for review December 18, 2024 13:41
@PiCode9560 PiCode9560 requested review from a team as code owners December 18, 2024 13:41
@PiCode9560
Copy link
Contributor Author

It's ready to review!

@PiCode9560 PiCode9560 force-pushed the softbody-apply-force-and-impulse branch 2 times, most recently from 5962e89 to beb2413 Compare December 18, 2024 18:17
@PiCode9560 PiCode9560 requested a review from a team as a code owner December 18, 2024 18:17
@PiCode9560 PiCode9560 requested a review from jrouwe December 27, 2024 18:02
@jrouwe
Copy link
Contributor

jrouwe commented Dec 27, 2024

Looks good to me!

One nitpick would be to update all of Jolt to 248253f88a5945c2032ffb397101afb9f88aeca5 or higher. I didn't initially suggest this because I knew there was another PR in progress that was touching the same files. But a full integrate can happen another time too.

@syntaxerror247 syntaxerror247 removed request for a team May 14, 2025 04:19
Copy link
Contributor

@jrouwe jrouwe left a comment

Choose a reason for hiding this comment

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

Latest changes look good to me.

@akien-mga akien-mga requested a review from mihe May 14, 2025 19:22
Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

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

Tested locally (rebased on top of master c3ae6aa), it works as expected when using GodotPhysics3D. However, when using Jolt Physics, nothing happens when trying to set an impulse (on a single point or all points).

Testing project: test_pr_100463.zip
Press R to apply an upwards impulse on a single point (and all points) at the same time.

@PiCode9560
Copy link
Contributor Author

PiCode9560 commented May 16, 2025

when using Jolt Physics, nothing happens when trying to set an impulse (on a single point or all points).

I tested it. It does work, but need a very large force for it to work. Apparently, in jolt physics, the more vertices added, the greater the force needed (for apply impulse and force).

@jrouwe do you think this is an intentional behaviour? The code looks like it work the same as godot physics, but on godot physics the force seems consistent no mater how many vertices there are.

Edit:
@Calinou
Actually, I figured it out, the soft body mass is set to 0 on jolt by default, if you set it to 1 it will work just like godot physics.

Copy link
Contributor

@mihe mihe left a comment

Choose a reason for hiding this comment

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

Found some very minor cosmetic issues, but looks good to me otherwise.

@PiCode9560 PiCode9560 force-pushed the softbody-apply-force-and-impulse branch from 52a252f to e2df211 Compare May 23, 2025 17:18
@PiCode9560 PiCode9560 force-pushed the softbody-apply-force-and-impulse branch from 6e3ceb3 to fe3aaa2 Compare May 23, 2025 19:05
@Repiteo Repiteo merged commit de2cd66 into godotengine:master May 26, 2025
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented May 26, 2025

Thanks! Congratulations on your first merged contribution! 🎉

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.

Add functions to apply forces and impulses on SoftBody nodes
7 participants