Body Dampening Inconsistent Across Different Update Rates.

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

Body Dampening Inconsistent Across Different Update Rates.

Postby MeltingPlastic » Mon Aug 13, 2018 2:42 pm

Hi Julio,

With the default body linear dampening rates. The effect is much more pronounced when running NewtonUpdate at 120hz as compared with 60hz. Is there a correct way the end result of body dampening can be inversely scaled with the timestep duration? So as the simulation looks more coherent when switching update rates?

When I set the dampening rates to 0.0f the simulations seem very similar across different update rates with the exception of stability which is to be expected.

I am assuming angular damping is doing the same thing but I have not tested it.
MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm

Re: Body Dampening Inconsistent Across Different Update Rate

Postby Julio Jerez » Mon Aug 13, 2018 3:34 pm

There is not way to get that equal at different update rates because damping if a not linear function.
It already considering the time steps scaling but that assumes the body velocity is not affected by externals forces.

This is the nature of numerical integration, the smaller integration step the more accurate it is.
what most people do is that the run the simulation at a fix rate. But I do not know how to do numerical integration the always produce the same result independent of the integration step.

Below is the function that calculate that adjust the damping coefficient to math the time step is this.
It caches the time step because assumes fix time step and because the Pow function is quite expensive to run thousand of time per frame.
try commenting out the read and see if there is a bug with the caching, but Like I said the
compensation will only generate correct result if the body in moving under the effect for the drag force and not other forces are action on it.

Code: Select all
DG_INLINE const dgVector& dgDynamicBody::GetDampCoeffcient (dgFloat32 timestep)
{
[color=#FF4040]// try commenting this line out to see if there is a bug.[/color]
   if (dgAbs(m_cachedTimeStep - timestep) > dgFloat32(1.0e-6f))
        {
      m_cachedTimeStep = timestep;
      const dgFloat32 tau = dgFloat32(1.0f) / (dgFloat32(60.0f) * timestep);
      m_cachedDampCoef.m_x = dgPow(dgFloat32(1.0f) - m_dampCoef.m_x, tau);
      m_cachedDampCoef.m_y = dgPow(dgFloat32(1.0f) - m_dampCoef.m_y, tau);
      m_cachedDampCoef.m_z = dgPow(dgFloat32(1.0f) - m_dampCoef.m_z, tau);
      m_cachedDampCoef.m_w = dgPow(dgFloat32(1.0f) - m_dampCoef.m_w, tau);
   }
   return m_cachedDampCoef;
}


Engines which are impulse based can do this better than newton because they first integrate external forces and them clip impulses to resolve constraint violation, this make those engine first order differential equations integrators.
This can make engines that run fast and stable but with the very wrong physics simulation, because the equation of motion say the motion of a body is the summation of all forces, not the summation of all impulses.

Newton apply the external forces, them calculate the reactions forces and finally integrate force and them integrate velocity. This make newton a second order integrator.

Most people do not care about these thongs, but I am telling you so that you know what you get into.
I try to minimize the maximum number of cheats in the engine, but this implied some thing will be different.
This is the secret that makes in general Newton a better physics simulator than impulse based which are basically collision systems that resolve interpenetration at the expenses of really wrong physics behavior.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Body Dampening Inconsistent Across Different Update Rate

Postby Julio Jerez » Mon Aug 13, 2018 3:40 pm

When I set the dampening rates to 0.0f the simulations seem very similar across different update rates with the exception of stability which is to be expected.


yes that will make it more similar, but even for a body in free fall it will eventually yield different simulation.
the reason that is very similar is because the Newton Integration is semi implicit, that is uses the velocity at the end of the time step as the velocity at the beginning of the step.
the yield a fart more stable simulation by and it is why is somewhat resilient to time step variation.

like I said, Numerical integration of non linear functions is a function of the integration step therefore different rates will yield different behaviors.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Body Dampening Inconsistent Across Different Update Rate

Postby MeltingPlastic » Tue Aug 14, 2018 2:29 pm

Good Stuff - this is why I'm using newton :).

I wanted to explore further so I made a comparison graph comparing NewtonBodySetLinearDamping and my own custom force that is calculated by:
Code: Select all
Vector3 dragForce = -vel.Normalized()*(vel.LengthSquared())*0.005f;


The first pic in each graph is a body with NewtonBodySetLinearDamping (0.5) and the second pic is a body with the custom force applied instead.

each body is set with an initial velocity away from the camera.
each graph shows distance away from the camera:

https://drive.google.com/open?id=1GEFswDKqmFmxpkd6AGQuzCd0y-yul0ZF


Is there a potential simplification where NewtonBodySetLinearDamping would apply external forces similar to my custom force? Maybe the function should be removed?

My goal is not to allow changing update rates at runtime or anything. I just want any set properties to reflect approximately the same behavior if someone changes engine settings.

Edit: I realize now I didn't take mass into account. but the effect should still be there because both test spheres have equal mass.
MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm

Re: Body Dampening Inconsistent Across Different Update Rate

Postby Julio Jerez » Tue Aug 14, 2018 5:41 pm

the function does not need to be removed, you can the set the coefficient to zero and take control on the force and torque callback.
there is one difference, if you do that in a force and torque callback them the scene will never go to sleep since the velocity will always be changing and that will be interpreted as a change of the external force.

This is the reason why the damping force is not applied as a user force like Newtonian physics states.
according to Newtonian physics the motion of a body is dictated by:

m * a = sum (f1 + f2 + ... + fn)

some of those forces are the reaction forces, some are the external force and the other is the drag.
external and internal forces do not depend of the body velocity, but drag does.

so for perfaromce and implementation convenient, the engine let the user apply the external force, the solver calculate the internal force but the drag is delegated to the solver to prevent entire island from waking on if one body change its velocity even by a very small value.

if you take over, then it will defeat all that logic. In general this works well, but if you need to take control of drag for some objects, you just do it for the objects that you need too by setting drag for those objects to zero and letting the engine apply the drags to the rest of the scene at the solver lever.
I do that for some special object like vehicles.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Body Dampening Inconsistent Across Different Update Rate

Postby MeltingPlastic » Tue Aug 14, 2018 6:05 pm

Thanks for the explanation!
To support both cases I have the following public function on my RigidBody Class:
Code: Select all
        /// Set linear velocity.
        void SetLinearVelocity(const Vector3& velocity);

        /// Set linear damping factor (0.0 to 1.0) default is 0
        void SetLinearDamping(float dampingFactor);

        /// Set Angular Damping factor (0.0 to 1.0) for angle component. default is 0 damping is in world space
        void SetAngularDamping(const Vector3& angularDamping);

        /// Set the internal linear damping - this is used internally by the newton solver to bring bodies to sleep more effectively.(0.0 to 1.0) default is zero
        void SetInternalLinearDamping(float damping);

        /// Set the internal angular damping - this is used internally by the newton solver to bring bodies to sleep more effectively. (0.0 to 1.0) default is zero
        void SetInternalAngularDamping(const Vector3& angularDamping);

MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm


Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 5 guests

cron