matter-js
matter-js copied to clipboard
Updating body not accounting for delta time when only velocity is set?
I'm seeing differing body speeds (visually, not body.speed) when framerates differ. Movement is meant be framerate independent but it doesn't appear to be with respect to only velocity. I think this line is the issue (in Body.update()).
body.velocity.x = (velocityPrevX * frictionAir * correction) + (body.force.x / body.mass) * deltaTimeSquared;
body.velocity.y = (velocityPrevY * frictionAir * correction) + (body.force.y / body.mass) * deltaTimeSquared;
The logic here will disregard delta time if force == 0 and will thus update the body with the same velocity if our frame rate is 60 or 30. Am I missing something, or using the engine wrong?
Mike
Any comment about this one?
I noticed this as well and I'm having a pretty hard time wrapping my head around it. I'm probably misunderstanding the math, but it seems like velocity isn't distance / time
but is more like distance / timestep
. I'm sure this makes sense to the engine but it makes dealing with and changing velocities super confusing.
It does seem strange but this actually falls out of the math from position Verlet integration:
xi+1 = xi + (xi - xi-1) + a * dt * dt
Check out this derivation, note that this assumes a constant time step. To account for a changing time step the author introduces a time correction scheme, which is what is implemented in the engine, though it's only intended for handling short dips since it's not that accurate. Hopefully that helps.
Oh ok, thank you so much. I see how this all works now, indeed matter.js is implementing the time correction scheme proposed in that article, however calling setVelocity() on a body updates the body's previous position, which essentially sets the velocity to units per delta-time-of-last-frame rather than normalizing it to something like units per second, or whatever. So really I need to scale the initial velocity I give my bodies to mean the same thing regardless of frame rate.
It does seem strange but this actually falls out of the math from position Verlet integration:
xi+1 = xi + (xi - xi-1) + a * dt * dt
Check out this derivation, note that this assumes a constant time step. To account for a changing time step the author introduces a time correction scheme, which is what is implemented in the engine, though it's only intended for handling short dips since it's not that accurate. Hopefully that helps.
I think the formula is correct (see also Wikipedia Velocity integration).
According to my understanding, your code in Body.update
calculates essentially
v[i] = (x[i] - x[i-1])
v[i+1] = v[i] + a * dt * dt
x[i+1] = x[i] + v[i+1]
However, velocities should be defined as the difference of current and previous position divided by the time step to make it "physically correct" i.e.
v[i] = (x[i] - x[i-1]) / dt
v[i+1] = v[i] + a * dt
x[i+1] = x[i] + v[i+1] * dt
This eliminates the strange dt * dt
and the result of the position update is the same as before, but the velocity update is different/correct.
@Qbyte248 it looks like you're assuming a fixed timestep there, which as it stands the engine does not assume, so it can't be simplified or rearranged that way in this case (you'll need a dt
and a dt-1
term).
The latest discussion on this topic is found in the PR #777 which intends to normalise velocities among other things, please do try that out and help review if you're interested.
Closing as I think this was covered by #777 which is now released in 0.19.0
(see the release notes). Thanks again.