Metres, Seconds and Newtons in PhysicsJS
I love PhysicsJS. Almost exactly what it says on the tin: modular, extendable and easy-to-use (it's also fun!). But I was missing something.
At first I was lost. The default gravity acceleration is 0.0004. Well, 0.0004 what?
The creator himself had an answer for me: pixels per millisecond squared.
Doing the math (and dandelany did it fine) it means the default scale of a simulation is forty one pixels per metre.
It's all very interesting (I really think so =P) and I suppose it's just fine for most cases.
But I wanted something different. I wanted to be able to use realistic values for my input and then convert output as needed. I wanted to be able to set this pixels per metre ratio easily (and be able to change it whenever I want, even during the simulation, I mean).
If I have a simulation of ball falling I want to be able to set gravity acceleration as 9.807 (metres per second squared) to simulate earth or just changed it to 1.622 to simulate the gravity acceleration on the moon. I want to read these values in the code. I want to change the metre per pixel ratio to ten or five and see this ball falling apparently slowly because it's like I'm seeing it from very far...
All this also made easier for to implement friction against background, as in a top-down view and air drag as in a 2.1d simulation. (See Burak Kanber's amazing article Modeling Physics in Javascript: Gravity and Drag)
The Kick
I initially tested my approach with a few problems.
The first was How much Force Does the Average Soccer Player Use to Kick the Ball?.
Here is the result: http://jsfiddle.net/slacktracer/zCc35/
The "kick" happens after two seconds. You will have to check the console to see how long it lasted (should be aprox. 0.05 seconds) and the resulting velocity (in metres per second).
Falling
The second problem was the falling ball problem.
You can see it here: http://jsfiddle.net/slacktracer/F5U6h/
You will also have to check the console for information. I used the following references (so you can test different values yourself): http://www.gravitycalc.com/ & Equations for a falling body.
How do I do it
In this situation, as in many others, time is of the essence.
I thought that if I could make PhysicsJS integrate using seconds instead of milliseconds everything else will follow. And it was something like that. I only had to change how acceleration got into the system.
In the verlet integrator it happens here:
// Apply acceleration
// v += a * dt * dt
state.vel.vadd( state.acc.mult( dtdt ) );
What I needed to do was turn these dts from milliseconds to seconds and then I would have acceleration in pixels per second squared (much closer to what I wanted).
v += a * dt * dt
Becomes:
v += a * (dt / 1000) * (dt / 1000)
then
v += a * (dt * dt) / (1000 * 1000)
then
v += a * (dt * dt) / 1000000
Now one pixels is the same as one metre. To make the metre easily configurable all we I need to do is multiply by whatever value I choose for a metre. Of course it's better done with a variable. An option of the integrator.
init: function( options ){
options.metre = options.metre || 41;
// call parent init
parent.init.call(this, options);
},
I'm keeping the aprox. default ratio as, well, default. =)
And then:
state.vel.vadd( state.acc.mult( ( dtdt / 1000000 ) * metre ) );
I created an integrator and called it metre-per-second-squared-verlet (not very creative, I suppose).
Looking at it now, it all seems very simple. But I had to bang my head against the wall a lot before I figured it all out. In other words, it was lots of fun! =P
Now, I'm not saying it is perfect or final by any means. (I'm not even sure it's a good approach. I still got a lot to learn about PhysicsJS internals) It seems to be working well for my needs so far and I do have have big plans for it.
This article is very crude, I know. I just had to put it out there. Hope it's useful to someone else and any and every feedback is welcome. Be it other approaches, how good or how bad is mine, tips on writing a better, more useful articles, questions. Anything really. If you read all this, thank you. It's very kind of you.
(I'll improve it or do a follow-up as needed or requested)
Also inspired by http://natureofcode.com/book/chapter-2-forces/
Written with StackEdit.
Written by slacktracer
Related protips
1 Response
You should put up your integrator on github as a proper module for PhysicsJS--I think anyone who wants to display values from their simulation will be interested in using it. Who knows, maybe Jasper will want to include it.