misyltoad / VPhysics-Jolt

Volt (VPhysics Jolt) is a replacement physics module for the Source Engine.
MIT License
1.26k stars 71 forks source link

Weight seems to not be taken into account? #23

Open SquirrelKiev opened 2 years ago

SquirrelKiev commented 2 years ago

Objects like models/props_c17/fence01a.mdl usually fall pretty slowly, however it falls as fast as every other object. The gravity gun is also able to pick up any object, no matter how big or small.

misyltoad commented 2 years ago

This may be due to missing air resistance. I wasn't quite sure how to implement that with Jolt. I considered using ApplyBuoyancyImpulse because it can do a drag factor and we use that for fluids, but I felt that was a big hammer to apply to everything and I was probably missing something really obvious.

Maybe @jrouwe would be able to give a pointer as to the best way to implement that here.

jrouwe commented 2 years ago

Air resistance is usually expressed through BodyCreationSettings::mLinearDamping / mAngularDamping.

misyltoad commented 2 years ago

I think that's too simple for what we want. We could implement our own proper drag.

We get a drag coefficient per-object + total orthographic area per-axis per-shape, and air density from the environment.

In theory we can calculate the drag basis for an object on each axis, and use that with the per-object drag coefficient to get the drag in any given direction and use that with the air density to calculate proper drag velocity to take off each step.

I guess the math isn't that complex here that we need assistance from Jolt to do it. I just thought I was missing stuff that allows for more complex drag implementations to be done.

misyltoad commented 2 years ago

(We could also maybe calculate this when parameters get updated and use mLinearDamping and mAngularDamping if Jolt offered these as Vector quantities that affect velocity in local-space instead of Scalar.)

jrouwe commented 2 years ago

I'm not sure if there are enough use cases for wanting linear/angular damping to be a vector. It's simple enough, but it will cost 4 floats extra per body and I don't know of any other physics engines that have implemented it that way.

What Jolt does internally for drag is basically: At the beginning of PhysicsSystem::Update, for every dynamic body call MotionProperties::ApplyForceTorqueAndDragInternal

and the interesting code is this:

mLinearVelocity *= max(0.0f, 1.0f - mLinearDamping * inDeltaTime);
mAngularVelocity *= max(0.0f, 1.0f - mAngularDamping * inDeltaTime);

So if you add this loop before you call PhysicsSystem::Update (or do it as a PhysicsStepListener) and convert your damping vector from local to world space and then do a component wise multiplication, I think you're done.

Note that if you have a drag coefficient, you may actually be better off applying the drag formula to the velocity directly instead of going through the damping formula. I'm not sure which one Source uses because there are multiple options, but the buoyancy code in Jolt uses this one:

Drag force = 0.5 Fluid Density (Velocity of fluid - Velocity of center of buoyancy)^2 Linear Drag Area Facing the Relative Fluid Velocity

Make sure you don't flip the velocity with your force.