Open mobileben opened 5 years ago
I've been doing some more investigation around this. Much like in this issue #603, I found I need roughly the same corrective values as that author. In that issue, he cites about how the value is derived to cancel out the delta time squared.
I was looking for a way to come up with deriving that number based on known information since it seems we should have a way to get a good estimate of what the engine would do (there actually doesn't see to be a great way to do it).
This code generates roughly the correct vy
. The resulting value does need to be scaled by 1.01
(roughly) to reach the desired height. This value will be referenced again below.
let g = world.gravity.y // Note gravity is positive since y increases downwards
let correction = 1000 * (1/60) * (1/60)
let h = ball.getPosition().y * correction // In theory, this should be the distance of the ball to the top of the screen
let vy = - Math.sqrt(2 * g * h)
I should also note, that in my test, I added box2d support. I have a setup where I have side by side balls, where one ball is based on matter and the other is based on box2d.
The balls start from the top of the screen and drop to verify gravity is working the same. Using a box2d scale of 100, I can see the fall of the ball is pretty much identical. Until the hit of the ground ... here things deviate slightly. I have found a restitution
of 1 with matter
is approximately equal to a restitution of 0.49498995 in box2d. Both balls are close enough on the bounce.
Moreover, I have found when using iforce2d's formula (link below) to calculate the vertical velocity opposed to the formula I was using, the box2d results are pretty much as expected (I print out the actual height reached for each ball and compare it to the desired height). Here's some sample output to the console as an example:
Box2d Projected height = 6.092009544372559, actual distance 609.2009544372559
Matter Distance traveled 600.869167694045
Box2D Distance traveled 609.1531753540039
This is his formula (this is based on Box2D, hence b2Gravity
).
function calculateVerticalVelocityForHeight(height) {
if (height <= 0) {
return 0.0
}
var t = 1 / 60.0
var stepG = t * t * b2Gravity.y
var a = 0.5 / stepG
var b = 0.5
var c = height
var qSol1 = (-b - Math.sqrt(Math.abs(b * b - 4 * a * c))) / (2 * a)
var qSol2 = (-b + Math.sqrt(Math.abs(b * b - 4 * a * c))) / (2 * a)
var v = qSol1
if (v < 0) {
v = qSol2
}
return v * 60.0
}
I have not managed to make figure out how to create a version of calculateVerticalVelocityForHeight
which will generate the correct velocity for matter.js.
Here is an example of a run. Box2d is on the right.
Both engines use Verlet integration, so I would expect roughly the same results.
But I think one thing based on reviewing #179, #240, #584, and #603 is that there seems to be a need for a better explanation of converting coordinates as well as how to derive more accurate values like in this case.
Right now, matter.js is operating on a 1:1 for pixels. box2D is a scale of 100. box2D, at least from this case, seems more predictable/derivable and was actually quite easy to get expected results.
I'd love to better understand how correction
in my code above is derived (the "why"), where the correction really needs to be applied (and "why"), as well as how to properly calculate the proper velocity. It just seems like there are some "magic numbers" that are needed to make it work, which I think is some of the basis of those issues I've cited.
As another note, when I used the
vy = sqrt(2 * g * h)
Method for deriving the initial velocity is applied to both matter and box2d, the results are nearly identical. I of course still have to use the correction
value in the case of matter.
Based on https://www.iforce2d.net/b2dtut/projected-trajectory, I sort of get why you need to calculate based on time steps versus seconds. I need to go through the math a bit more, but it does make sense. Using his version, it was roughly 1.01
scaled up from when using the physics formula.
Another curious thing I noticed from my quick look at Verlet integration and how it works is your formulas seem to be slightly different. Note I didn't go through the math entirely. I'm sure you have your reasons. I'm just wondering is this also is a source for the weirdness.
Hope this isn't taken the wrong way. I think the engine is quite nice and you've done a great job. Just noticing some pain points in usage which seem valuable not just to me, but to others as well.
Any updates on this? Also struggling with impulse / force required to reach certain height.
I was following around with trying to predict trajectories. Right now I'm isolating just the vertical component using the basic formula
where
vy
is the vertical component of the initial velocity,g
is gravity, andh
is the height to travel. I currently havefrictionAir
on the ball set to 0.I have a basic setup where the ball is on the ground. A mouse button press will
setVelocity
on the ball, using the calculatedvy
.What results is the ball going way higher than expected. Either my understanding of the correct way of using gravity is incorrect or I'm doing something else wrong.
The isolated code (full code will also be included at the end) for just setting the velocity is:
Clearly it seems trying to use
world.gravity.y
is the naive approach. It appears I'm missing some conversion or perhaps my math is off.I've tried multiplying in the
world.gravity.scale
but in that case, the ball doesn't even launch.