|
Author |
Topic: Physics engine bug... Can't find it. (Read 536 times) |
|
Fish-face
|
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
|
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
|
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
|
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
|
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#~
|
|
|
|