Bouncing ball with Euler integration loses speed over time

I am trying to implement free fall motion of a ball towards a plane.

I implemented collision detection and if collision happens, I change sign of velocity of a ball so it bounces off and climbs back up.

Now, it should climb back to its original position if there is no loss of energy, but after some testing I realized that after each bounce I have less speed than the bounce before.

Part of my code related to this:

if (collision)
{
velocity.y = -velocity.y;

std::cout << velocity.y << std::endl;
}

velocity.y += gravityAccel * ts.getSeconds();

position.x += velocity.x * ts.getSeconds() + ent.getComponent<RigidBody>().InitVelocity.x * ts.getSeconds();
position.y += velocity.y * ts.getSeconds() + ent.getComponent<RigidBody>().InitVelocity.y * ts.getSeconds();
position.z += velocity.z * ts.getSeconds() + ent.getComponent<RigidBody>().InitVelocity.z * ts.getSeconds();


I think that my problem lies in the calculations that happen right before ball reaches its maximum height. I think that he ball has some speed that is less than the speed change calculated by the next time step, so what I get is negative speed and reversal of motion direction along y axes a bit before it should actually happen. If this is so, I am trying to figure out the best way to solve this problem and have relatively nice free fall motion.

I know, you could say that this is not a bug but a feature since I have energy loss without asking for it. :)

• Why are you adding both velocity and ent.getComponent<RigidBody>().InitVelocity to the position? What does this latter velocity represent, that's distinct from the velocity stored in the velocity variable? Commented Dec 19, 2022 at 21:34
• @DMGregory It is initial velocity, that the body has when it starts to move, eg if you throw it by hand, it is just the velocity body starts with and in this case it is zero. Commented Dec 24, 2022 at 7:13
• Shouldn't that just be seeded into the velocity field a single time, at the moment of the throw? Commented Dec 24, 2022 at 9:46
• I don't know if it should but I am just trying to solve collisions first, this was a minor bug that bugged me a bit. Thanks for clarifying that this is euler integration. Commented Dec 24, 2022 at 23:40

You are using the velocity at the end of the interval to integrate the position (velocity updated before position). So position never reaches to the top. Every hop, it loses height.

You need to use the average velocity in the interval ts.getSeconds()

vi -> velocity at the end of previous update
vi+1 -> velocity at the end of current update
vi+1 = vi + a * dt;
(vi + vi+1) / 2.0 = (vi + (vi + a * dt)) / 2.0 = vi + 0.5 * a * dt


(assuming constant acceleration)

If you use that velocity when integrating the position, you will get

position += vi * dt + 0.5 * a * dt * dt    // use initial interval velocity i.e. update position before velocity


or

position += 0.5 * (vi + vi+1) * dt    // save velocity before updating it, and use both velocities to get the position

• Although I solved it myself I am accepting this as a good answer. I realized that I should integrate eactly in this case since I am actually calculating the area under the linear function. So I just added the area of a little triangle to every rectangle. Commented Dec 24, 2022 at 7:16