FAQ
Cover
This is the archive Discourse for the Processing (ALPHA) software.
Please visit the new Processing forum for current information.

   Processing 1.0 _ALPHA_
   Programming Questions & Help
   Programs
(Moderators: fry, REAS)
   Physics engine bug... Can't find it.
« Previous topic | Next topic »

Pages: 1 
   Author  Topic: Physics engine bug... Can't find it.  (Read 536 times)
Fish-face

308232952308232952thedemonsheep WWW Email
Physics engine bug... Can't find it.
« on: Jul 30th, 2004, 11:20pm »

Hi, I recently started programming with processing and firstly, I'd like to say what brilliant language it is - easy, powerful and brilliant for the type of things I like creating.
 
Anyway, I have a bug in a physics engine I'm working on. There are two implementations - one involving springs, the other not. With springs, when friction is set to nothing, the system accelerates. In the other, the system decelerates.
I can't work out why this is... Could you have a go?
 
The URL for without springs is http://www.fishface.a.la/processing/processing.php?q=3
For with, http://www.fishface.a.la/processing/processing.php?q=4
 
Thanks for any help you can give.
 

--

The C@ S@ on the M@
=Fish-Face=
~#Chris#~
narain


Re: Physics engine bug... Can't find it.
« Reply #1 on: Jul 31st, 2004, 5:38am »

The link isn't opening for me...
Could you post your code here?
 
Fish-face

308232952308232952thedemonsheep WWW Email
Re: Physics engine bug... Can't find it.
« Reply #2 on: Jul 31st, 2004, 10:31am »

Awoops - self hosted. You probably tried when the server was off! Here's the code for no springs:
 
Code:
float friction;
float gravity;
float wind, windy;
 
int keyPress=0;
boolean usewind=true;
 
int oldMouseY, oldMouseX;
 
int massnum=5, maxmass=100;
boolean starting = true;
 
Mass[] Masses = new Mass[maxmass];
 
void setup() {
  size(250,200);
  noStroke();
  ellipseMode(CENTER_DIAMETER);
  colorMode(HSB);
   
  friction=0.99;
  gravity=0.2;
  wind=0.5;
  windy=0.1;
   
  for(int i=0; i<maxmass; i++) {
    Masses[i]=new Mass((int)random(200),(int)random(200),random(5)+4);
  }
}
 
void loop() {
  if(keyPressed) {
    if(keyPress==0) keyPress=1;
    else keyPress=-1;
  } else {
    keyPress=0;
  }
  if(keyPress==1) {
    if(key == UP && massnum < maxmass-1) {
 massnum++;
 //Masses[massnum-1]=new Mass((int)random(200),(int)random(200),random(5)+4);
    } if(key == DOWN && massnum > 0) {
 massnum--;
 //Masses[massnum]=new Mass((int)random(200),(int)random(200),random(5)+4);
    }
     
    if(key == 'w') {
 usewind=!usewind;
    }
     
    if(key == 'r' && friction > 0) {
 friction-=0.01;
    } if(key == 'f' && friction < 2) {
 friction+=0.01;
    }
     
    if(key == 't' && gravity < 10) {
 gravity+=0.1;
    } if(key == 'g' && gravity > -10) {
 gravity-=0.1;
    }
  }
 
  background(0);
   
  if(gravity>0) fill(0,0,255);
  else fill(0,0,128);
  rect(205,100-gravity*9,15,gravity*9);
   
  if(friction>1) fill(0,0,128);
  else fill(0,0,255);
  rect(230,190-(2-friction)*90,15,(2-friction)*90);
   
  if(usewind) {fill(50,255,255); ellipse(205,195,8,8);}
   
  stroke(0,0,255);
  line(200,0,200,200);
  noStroke();
   
  wind=wind+random(0.4)-0.2;
  windy=windy+random(0.1)-0.05;
   
  if(wind>1) wind=1;
  if(wind<-1) wind=-1;
  if(windy>0.4) windy=0.4;
  if(windy<-0.4) windy=-0.4;
   
  for(int i=0; i<massnum; i++) {
    Masses[i].Force(0,gravity);
    if(usewind) Masses[i].Force(wind,windy);
    Masses[i].Update();
  }
}
 
void keyPressed() {
   
}
 
void keyReleased() {
   
}
 
void mousePressed() {
  if(mouseX>205 && mouseX<220) {
    gravity=-(float)(mouseY-100)/9;
  }
  if(mouseX>230 && mouseX<250) {
    friction=(float)((mouseY-2))/90;
  }
}
 
class Mass {
  float posx, posy; //Current position
  float newx, newy; //New position
  float velx, vely; //Velocity, to work out new position
   
  float accel; //Acceleration, to work out velocity
  float mass;  //Mass, to work out acceleration
   
  int id;      //What index in the array?
   
  boolean mouseIn;
 
  Mass(float x, float y, float m) {
    newx=x; newy=y;
    mass=m;
  }
   
  void Force(float force_x, float force_y) {
    accel=force_x/mass;
    velx=velx+accel;
     
    accel=force_y/mass;
    vely=vely+accel;
  }
   
  void Update() {
    velx=friction * velx;
    vely=friction * vely;
     
    if(!mousePressed) {
 mouseIn=false;
    } else if(mouseIn()) {
 mouseIn=true;
    }
     
    if(mouseIn) {
 Force(mouseX-newx, mouseY-newy);
    }
     
    if(newx+velx>195) {velx=-velx; newx=195;}
    else if(newx+velx<5) {velx=-velx; newx=5;}
    else {newx=newx+velx;}
     
    if(newy+vely>195) {vely=-vely;newy=195;}
    else if(newy+vely<5) {vely=-vely;newy=5;}
    else {newy=newy+vely;}
     
    for(int i=0;i<massnum;i++) {
 float disX=newx-Masses[i].newx;
 float disY=newy-Masses[i].newy;
 if(sqrt(sq(disX) + sq(disY)) < 10 ) {
   Masses[i].Force(velx-disX/2,vely-disY/2);
   this.Force(-velx+disX/2,-vely+disY/2);
 }
    }
     
    fill((150+velx*vely*20)%255,(200+vely*20)%255,200);
    ellipse(newx,newy,10,10);
  }
   
  boolean mouseIn() {
    float disX = newx - mouseX;
    float disY = newy - mouseY;
    if(sqrt(sq(disX) + sq(disY)) < 5 ) {
 return true;
    } else {
 return false;
    }
  }
}
 

--

The C@ S@ on the M@
=Fish-Face=
~#Chris#~
Fish-face

308232952308232952thedemonsheep WWW Email
Re: Physics engine bug... Can't find it.
« Reply #3 on: Jul 31st, 2004, 10:33am »

And for springs:
 
Code:
float friction;
float gravity;
float wind, windy;
 
int keyPress=0;
boolean usewind=false;
 
int oldMouseY, oldMouseX;
 
int massnum=10, maxmass=100;
boolean starting = true;
 
Mass[] Masses = new Mass[maxmass];
float[][][] springs =  new float[maxmass][maxmass][3];
 
void setup() {
  size(250,200);
  noStroke();
  ellipseMode(CENTER_DIAMETER);
  colorMode(HSB);
   
  friction=0.99;
  gravity=0.2;
  wind=0.5;
  windy=0.1;
   
  for(int i=0; i<maxmass; i++) {
    Masses[i]=new Mass((int)random(200),(int)random(200),random(5)+4);
  }
  /*Masses[0]=new Mass(100,100,8);
  Masses[1]=new Mass(80,100,8);
  Masses[2]=new Mass(120,100,8);
  Masses[3]=new Mass(100,120,8);
  Masses[4]=new Mass(100,80,8);*/
  for(int i=0;i<maxmass;i++) {
    for(int o=0;o<maxmass;o++) {
 if(i != o) Spring(i,o,0.5,50,0.5);
    }
  }
}
 
void loop() {
  if(keyPressed) {
    if(keyPress==0) keyPress=1;
    else keyPress=-1;
  } else {
    keyPress=0;
  }
  if(keyPress==1) {
    if(key == UP && massnum < maxmass-1) {
 massnum++;
 //Masses[massnum-1]=new Mass((int)random(200),(int)random(200),random(5)+4);
    } if(key == DOWN && massnum > 0) {
 massnum--;
 //Masses[massnum]=new Mass((int)random(200),(int)random(200),random(5)+4);
    }
     
    if(key == 'w') {
 usewind=!usewind;
    }
     
    if(key == 'r' && friction > 0) {
 friction-=0.01;
    } if(key == 'f' && friction < 2) {
 friction+=0.01;
    }
     
    if(key == 't' && gravity < 10) {
 gravity+=0.1;
    } if(key == 'g' && gravity > -10) {
 gravity-=0.1;
    }
  }
 
  background(0);
   
  if(gravity>0) fill(0,0,255);
  else fill(0,0,128);
  rect(205,100-gravity*9,15,gravity*9);
   
  if(friction>1) fill(0,0,128);
  else fill(0,0,255);
  rect(230,190-(2-friction)*90,15,(2-friction)*90);
   
  if(usewind) {fill(50,255,255); ellipse(205,195,8,8);}
   
  stroke(0,0,255);
  line(200,0,200,200);
  noStroke();
   
  wind=wind+random(0.4)-0.2;
  windy=windy+random(0.1)-0.05;
   
  if(wind>1) wind=1;
  if(wind<-1) wind=-1;
  if(windy>0.4) windy=0.4;
  if(windy<-0.4) windy=-0.4;
   
  for(int i=0; i<massnum; i++) {
    Masses[i].Force(0,gravity);
    if(usewind) Masses[i].Force(wind,windy);
    for(int s=0; s<massnum; s++) {
 if(springs[i][s][0]>0) {
   float distX=(float)Masses[i].newx-Masses[s].newx;
   float distY=(float)Masses[i].newy-Masses[s].newy;
   float dist=sqrt(sq(distX)+sq(distY));
   if(int(dist)!=springs[i][s][1]) {
   float targX=(float)distX/(dist/springs[i][s][1]);
   float targY=(float)distY/(dist/springs[i][s][1]);
   
   float forceX=(float)-springs[i][s][0]*(distX-targX)*springs[i][s][2];
   float forceY=(float)-springs[i][s][0]*(distY-targY)*springs[i][s][2];
   
   Masses[i].Force(forceX,forceY);
   }
   stroke(0,0,255); line(Masses[i].newx,Masses[i].newy,Masses[s].newx,Masses[s].newy);
   noStroke();
 }
    }
    Masses[i].Update();
  }
}
 
void Spring(int m1, int m2, float k, int distance, float damp) {
  springs[m1][m2][0]=k;
  springs[m1][m2][1]=distance;
  springs[m1][m2][2]=damp;
  springs[m2][m1][0]=k;
  springs[m2][m1][1]=distance;
  springs[m2][m1][2]=damp;
}
 
void mousePressed() {
  if(mouseX>205 && mouseX<220) {
    gravity=-(float)(mouseY-100)/9;
  }
  if(mouseX>230 && mouseX<250) {
    friction=(float)((mouseY-2))/90;
  }
}
 
class Mass {
  float posx, posy; //Current position
  float newx, newy; //New position
  float velx, vely; //Velocity, to work out new position
   
  float accel; //Acceleration, to work out velocity
  float mass;  //Mass, to work out acceleration
   
  int id;      //What index in the array?
   
  boolean mouseIn;
 
  Mass(float x, float y, float m) {
    newx=x; newy=y;
    mass=m;
  }
   
  void Force(float force_x, float force_y) {
    accel=force_x/mass;
    velx=velx+accel;
     
    accel=force_y/mass;
    vely=vely+accel;
  }
   
  void Update() {
    velx=friction * velx;
    vely=friction * vely;
     
    if(!mousePressed) {
 mouseIn=false;
    } else if(mouseIn()) {
 mouseIn=true;
    }
     
    if(mouseIn) {
 Force(mouseX-newx, mouseY-newy);
    }
     
    if(newx+velx>195) {velx=-velx; newx=195;}
    else if(newx+velx<5) {velx=-velx; newx=5;}
    else {newx=newx+velx;}
     
    if(newy+vely>195) {vely=-vely;newy=195;}
    else if(newy+vely<5) {vely=-vely;newy=5;}
    else {newy=newy+vely;}
     
    for(int i=0;i<massnum;i++) {
 float disX=newx-Masses[i].newx;
 float disY=newy-Masses[i].newy;
 if(sqrt(sq(disX) + sq(disY)) < 10 ) {
   Masses[i].Force(velx-disX/2,vely-disY/2);
   this.Force(-velx+disX/2,-vely+disY/2);
 }
    }
     
    fill((150+velx*vely*20)%255,(200+vely*20)%255,200);
    ellipse(newx,newy,10,10);
  }
   
  boolean mouseIn() {
    float disX = newx - mouseX;
    float disY = newy - mouseY;
    if(sqrt(sq(disX) + sq(disY)) < 5 ) {
 return true;
    } else {
 return false;
    }
  }
}
 

--

The C@ S@ on the M@
=Fish-Face=
~#Chris#~
fjen

WWW
Re: Physics engine bug... Can't find it.
« Reply #4 on: Jul 31st, 2004, 1:34pm »

on Jul 31st, 2004, 10:33am, Fish-face wrote:
Code:

.....
 
for(int i=0; i<massnum; i++) {
    Masses[i].Force(0,gravity);
    if(usewind) Masses[i].Force(wind,windy);
    for(int s=0; s<massnum; s++) {
      if(springs[i][s][0]>0) {
   // Masses[i].newx, Masses[i].newy are float allready
        float distX=(float)Masses[i].newx-Masses[s].newx;
        float distY=(float)Masses[i].newy-Masses[s].newy;
        float dist=sqrt(sq(distX)+sq(distY));
        if(int(dist)!=springs[i][s][1]) {
   // distX, distY, dist are float allready
        float targX=(float)distX/(dist/springs[i][s][1]);
        float targY=(float)distY/(dist/springs[i][s][1]);
   // all are float ...
        float forceX=(float)-springs[i][s][0]*(distX-targX)*springs[i][s][2];
        float forceY=(float)-springs[i][s][0]*(distY-targY)*springs[i][s][2];
        
        Masses[i].Force(forceX,forceY);
        }
        
....
 
void Spring(int m1, int m2, float k, int distance, float damp) {
  springs[m1][m2][0]=k;
  springs[m1][m2][1]=distance;
  springs[m1][m2][2]=damp;
  springs[m2][m1][0]=k;
  springs[m2][m1][1]=distance;
  springs[m2][m1][2]=damp;
 
....
 

 
removing the unneccesary typecasting "(float)" made it stop collapsing. there is no need to cast a float to a float ... not sure what's happening inside of java then.
 
replace the for-loop with:
Code:

for(int s=0; s<massnum; s++) {
 if(springs[i][s][0]>0) {
   float distX=Masses[i].newx-Masses[s].newx;
   float distY=Masses[i].newy-Masses[s].newy;
   float dist=sqrt(sq(distX)+sq(distY));
   if(int(dist)!=springs[i][s][1]) {
     float targX=distX/(dist/springs[i][s][1]);
     float targY=distY/(dist/springs[i][s][1]);
 
     float forceX=-springs[i][s][0]*(distX-targX)*springs[i][s][2];
     float forceY=-springs[i][s][0]*(distY-targY)*springs[i][s][2];
 
     Masses[i].Force(forceX,forceY);
   }
   stroke(0,0,255); line(Masses[i].newx,Masses[i].newy,Masses[s].newx,Masses[s].newy); noStroke();
 }
    }

 
hope this helps a little ... best flo.
 
Fish-face

308232952308232952thedemonsheep WWW Email
Re: Physics engine bug... Can't find it.
« Reply #5 on: Jul 31st, 2004, 2:11pm »

Didn't see any improvement...
 
I copied the Mass class into a new project, and it worked as expected with friction set to 1.
I tried commenting out all of the loop code bar Update(), too, and the problem persisted in the existing project. This would seem to indicate that the problem lies elsewhere... but I can't find it!
 
Possibly unrelated, but I noticed that as you decreased the friction, it became a number it shouldn't be. It goes to 0.9600004 or something similar. Then to 0.9700005...
 
Thanks for your help, so far!
 
EDIT: Correction, I realized that I'd not copied over the collision procedure. That last for loop in the Mass class was the culprit - the mass was colliding with itself.
However, with springs still has its error... It will accelerate even with friction < 1.
« Last Edit: Jul 31st, 2004, 2:36pm by Fish-face »  

--

The C@ S@ on the M@
=Fish-Face=
~#Chris#~
Pages: 1 

« Previous topic | Next topic »