Time scaling a single RigidBody

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By avencherus
:warning: Old Version Published before Godot 3 was released.

I’m familiar with OS.set_time_scale(), but I was curious if there is some simple way to apply time scaling to a single physics body like a RigidBody, without having to rewrite it’s integration.

so you want that your rigidbody to grow in relation to runtime?

use the _process(delta):

method. delta = difference since the last time _process got called.

you activate _process via self.set_process(true)

ingo_nikot | 2017-01-14 14:17

I’m familiar with delta. If there is a way to change the delta of one rigidbody’s physics loop, while leaving the rest unaffected, that’s what I would be looking for. I would prefer to leave the default rigid body physics going.

I want a local change to the delta on the physics of a single rigid body.

If you had like 10 falling balls, I was wondering if there would be a direct and easy way to alter 1 to have it’s physics performed with a smaller delta, say 50%. So that one ball would take twice as long to hit the ground, etc.

If it were 60 frames a second, I would hope it would still get 60 updates, but with a different time step, just making it move only half as much as it should if it were delta/2.

avencherus | 2017-01-14 15:59

Have you tried with _integrate_forces using reduced step?

eons | 2017-01-14 16:26

I have tried many things there, but so far I see no way to set only the time step there.

You can get a time step out of the PhysicsBodyDirectState, but that is useful for overriding and making your own integration. I’d like to let the RigidBodies perform with their default physics code. I just want to change their physics step sizes individually.

avencherus | 2017-01-14 16:30

“smaller delta, say 50%.”
set gravity scale to 0.5. he will accelerate with only 50%

i hope i did understand you correctly this time^^

ingo_nikot | 2017-01-14 16:37

Yeah, that’s only gravity though. If it bounces or has a impulse applied, it’s going to move normally according to those velocities, and the gravity will just be odd.

I would like the same effect as OS.set_time_scale(.5), but only on one RigidBody.

avencherus | 2017-01-14 16:43

Right, but what you mean is making a custom integrator after all, I guess.


I don’t know if other physics engines have that possibility or is all forced fake movement (highly probable).

And now thinking a bit more, maybe just affecting the step for linear and angular velocity calculations won’t be enough, I need to see the default integrator, may do some 2d experiments.

eons | 2017-01-14 17:05

I’m fairly sure it’s going to either be duplicating all the integration in GDScript as an override, or add the feature to the source and create a fork of it. So just hoping someone might have some trick up their sleeve that I overlooked. X)

avencherus | 2017-01-14 17:12

Maybe is just replicating this part in GDScript with the custom integrator(adds gravity and damps to velocity), I need to create some simple scenes to test.
https://github.com/godotengine/godot/blob/93ab45b6b5c4f8e0619e963156c983009d399a9d/servers/physics/body_sw.cpp#L524

eons | 2017-01-14 17:37

I’ll be looking at it too, let me know what you find.

I’m mostly tripped up by: angular_velocity+=_inv_inertia_tensor.xform(torque)*p_step;

Which is:

principal_inertia_axes_local = inertia_tensor.diagonalize().transposed();
principal_inertia_axes = get_transform().basis * principal_inertia_axes_local;

Basis tb = principal_inertia_axes;
Basis tbt = tb.transposed();
tb.scale(_inv_inertia);

_inv_inertia_tensor = tb * tbt;

And the inertia tensor: https://github.com/godotengine/godot/blob/93ab45b6b5c4f8e0619e963156c983009d399a9d/servers/physics/body_sw.cpp#L84

		inertia_tensor.set_zero();

			for (int i=0;i<get_shape_count();i++) {

				const ShapeSW* shape=get_shape(i);

				float area=get_shape_area(i);

				float mass = area * this->mass / total_area;

				Basis shape_inertia_tensor=shape->get_moment_of_inertia(mass).to_diagonal_matrix();
				Transform shape_transform=get_shape_transform(i);
				Basis shape_basis = shape_transform.basis.orthonormalized();

				// NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor!
				shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed();

				Vector3 shape_origin = shape_transform.origin - center_of_mass_local;
				inertia_tensor += shape_inertia_tensor + (Basis()*shape_origin.dot(shape_origin)-shape_origin.outer(shape_origin))*mass;


}

I’m not very familiar with physics engines, so I’m not terribly confident about verifying results or debugging.

avencherus | 2017-01-14 19:03

I was trying with GDScript and managed to replicate exact velocity -damp with custom integrator but scaling that is tricky because next steps quickly lower velocities at fixed damp, maybe everything needs to be faked to simulate slow motion with the script integrator.


The class Step_SW controls many things too

Here is the velocity integration part
https://github.com/godotengine/godot/blob/93ab45b6b5c4f8e0619e963156c983009d399a9d/servers/physics/step_sw.cpp#L272

eons | 2017-01-14 19:55