Problems with scaling time for Euler Approximation 2D Physics engine
in
Programming Questions
•
2 years ago
I'm trying to create a very simple 2D Physics engine that uses an Euler approximation to calculate each new step. The problem I'm having is that whenever I try changing the time step (dt) from "1", the engine seems to blow up, even when I'm simply trying to "predict" the next step and not commit it to the object's current state.
What I have is a ball, where when you click a force is generated to push the ball in the direction of the mouse click. While this is happening, I want the physics engine to calculate gravitational forces between the ball and several points around the screen, and combine these forces into the motion of the ball. I can get this to work reasonably well when dt is "1", but as I try to slow things down or speed them up I get this bugger of a problem.
Here are the relevant sections of my code,
The "ball" object (maybe later it'll get to be a proper spacecraft):
- class PhysicsState {
- PVector pos;
- PVector vel;
- PhysicsState() {
- pos = new PVector(0,0);
- vel = new PVector(0,0);
- }
- }
- class Spacecraft {
- PhysicsState state = new PhysicsState();
- PVector ThrustVector = new PVector(0,0);
- Spacecraft(float x,float y, float vmag, float angle) {
- float vx,vy;
- vy = vmag*sin(radians(angle));
- vx = vmag*cos(radians(angle));
- state.vel = new PVector(vx,vy);
- state.pos = new PVector(x,y);
- ThrustVector = new PVector(0,0);
- }
- void update(float delta_time){
- UpdateState(this,delta_time);
- }
- }
The actual force calculations and physics updating:
- PVector ForceVector(PVector Probe_position,PVector Mass_position,float Mass,float minDistance) { //Returns the force vector sum for a given position
- float Force; //temporarily stores data on magnitude of force
- float Distance; //temporarily stores data on distance between objects
- PVector vDir = PVector.sub(Probe_position,Mass_position); //direction force is acting
- Distance = vDir.mag();
- if(Distance<minDistance){Distance=minDistance;}
- vDir.normalize();
- Force = (cGravity*Mass)/(Distance*Distance);
- return (PVector.mult(vDir,Force));
- }
- PVector ForceCalc(Spacecraft P, float dt){
- //First, forces due to sun:
- PVector AccelSum = ForceVector(P.state.pos,Sun.pos,Sun.mass,Sun.sSize);
- for(int i=0;i<num_planets;i++) { //Now, forces due to planets:
- AccelSum.add(ForceVector(P.state.pos,Planet[i].pos,Planet[i].mass,Planet[i].pSize));
- }
- AccelSum.add(P.ThrustVector); //Include forces due to thrusters
- AccelSum.mult(dt); //Scale for time effects
- return (AccelSum); //Finally, take this and set total accelerations
- }
- void UpdateState(Spacecraft P,float dt) {
- PVector velocity = P.state.vel;
- velocity.mult(dt);//multiply by dt
- P.state.pos.add(velocity); //put resultant velocity into position...
- P.state.vel.add(ForceCalc(P,dt)); //add acceleration to velocity
- }
And lastly, here is what is driving me crazy. This function is simply supposed to return a potential future position based on an Euler approximation without affecting any of the above physics calculations. That is to say, implementing this function SHOULD NOT move the spacecraft. But, whenever I try to use it with a dt value not equal to "1", the rest of the engine blows up, sending the spacecraft's position and velocity vectors to infinity or NaN (not a number).
- PVector predictPosition(Spacecraft P, float dt){
- PVector vel;
- vel = new PVector(P.state.vel.x,P.state.vel.y);
- println();
- vel.add(ForceCalc(P,dt)); //add acceleration to velocity
- vel.mult(dt); //scale by delta time
- PVector position = P.state.pos;
- position.add(vel); //put resultant velocity into position...
- return (position);
- }
I have been banging my head on this one for several hours now, and I've got no clue how to fix it. Am I improperly using PVectors? Do I need to rename variables to be different between functions in processing/Java? Is there something fundamentally flawed with my approach?
I know the trick to getting an answer is asking a nice and clear question, all I want to know is why the predictPosition() function would cause changes to the actual spacecraft's position, and why I can't seem to change the dt value for either the predictPosition() or updateState() functions without things going out of control.
Thanks in advance for any advice you can give me!
-Nick
1