We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Optimizing gravity simulator
Page Index Toggle Pages: 1
Optimizing gravity simulator (Read 618 times)
Optimizing gravity simulator
Oct 7th, 2009, 9:11pm
 
Hi all. I've been playing around with a little n-body simulator for a while now, as a way to level up my coding skills. I've got the basic numerical engine working (using a leapfrog scheme) and have just switched over to opengl. I'm using peasy cam to allow you to fly around within the gravitational interaction, and study the tracks left in 3d. (Unfortunately, the openGL background refresh bug forces me to be constantly redrawing histroy, but it still seems to run smoother overall in openGL. )

I'm just starting to impliment interface and control features (being able to set velocity, mass, apply acceleration, change time step and G, etc) but thought I'd throw my core class up here first, on the chance someone might be able to suggest some optimization or trick I hadn't though of yet.


part of my setup code:
-=-=-

void setup() {
 pCam = new PeasyCam(this, w/2, h/2, 0, 500);
 pCam.setMinimumDistance(.05);
 pCam.setMaximumDistance(3000);    
 hint(DISABLE_OPENGL_2X_SMOOTH);
 hint(DISABLE_DEPTH_TEST);
 size(w, h, OPENGL);
 background(255);
 ellipseMode(CENTER);
 noStroke();
 smooth();
 resetMatrix();
 for (int i = 0; i <= bodies.length-1; i++) {
   bodies[i] = new Objects(random(w), random(h), random(-1000, 250),
   random(0,200));
 }
}

-=-=-
Part of my draw loop:
-=-=-

for (int i = 0; i <= bodies.length-1; i++) {  
     bodies[i].displace(i);
     bodies[i].displayHist(i);
}

-=-=-
Most of my Core class:
-=-=-

 float x;
 float y;
 float z;
 
 float xAccel;
 float yAccel;
 float zAccel;

class Objects {
 float xpos, ypos, zpos;
 float xVel, yVel, zVel;
 float[] xAcel = new float[bodies.length];
 float[] yAcel = new float[bodies.length];
 float[] zAcel = new float[bodies.length];  
 float xAcelTotal_0, yAcelTotal_0, zAcelTotal_0;
 float xAcelTotal_1, yAcelTotal_1, zAcelTotal_1;  
 float mass;
 float xDiff, yDiff, zDiff;
 float dSq;

 //history
 float[] xHist = new float[hist];
 float[] yHist = new float[hist];
 float[] zHist = new float[hist];  
 int s;  //onscreen size of the ellipse
 float gD = G / dSq;
 float product;  //this will be G * mass / dSq

 float objFill;

 Objects(float x_, float y_, float z_, float m_) {    
   xpos = x_;
   ypos = y_;
   zpos = z_;    
   xVel = 0;
   yVel = 0;
   zVel = 0;    
   mass = m_;
   mouseOverObjectTest = true;  //check to see if mouse is over a body
   fill(0);
   xAcelTotal_1 = 0;
   yAcelTotal_1 = 0;
   zAcelTotal_1 = 0;    
   xAcelTotal_0 = 0;
   yAcelTotal_0 = 0;
   zAcelTotal_0 = 0;    
   s = int(map(mass, 0, 500, 2, 17));  
   //s = int(map(mass, 0, 500, 20, 50));  
   ellipseMode(CENTER);

   //initialize the history array
   for (int i = 0; i < hist; i++) {
     xHist[i] = this.xpos;
     yHist[i] = this.ypos;
     zHist[i] = this.zpos;
   }      
 }

 void display(int m) {  
   if (cam) {          //check to see if we're panning -- if we are, draw the history, and stop time
     if (m == 0) {    //wipe the screen clear at the start of every loop throught the array of bodies
       background(255);        
     }    
     for (int j = 0; j < hist; j++) {
       pushMatrix();
       translate(0,0,zHist[j]);
       fill(0, objFill, objFill, 40);
       ellipse (xHist[j], yHist[j], s, s);
       popMatrix();
     }
   }
   else {      //if we're not fooling with the camera just draw draw the present moment and don't wipe the screen    
     pushMatrix();
     translate(0, 0, zpos);
     fill(0, objFill, objFill, 40);      
     ellipse(xpos, ypos, s, s);
     fill(255);
     popMatrix();
   }    
 }

 void displayHist(int m) {           //a refresh function for clearing jitter and other junk from the screen. Ultimately, there should
                                //probably just be a displayHist() and a displayPos() -- none of this either/or junk.
   if (m == 0) {    //wipe the screen clear at the start of every loop throught the array of bodies
     background(255);        
   }  
   for (int j = 0; j < hist; j++) {
     pushMatrix();
     translate(0,0,zHist[j]);
     fill(0, objFill, objFill, 40);
     ellipse (xHist[j], yHist[j], s, s);
     popMatrix();
   }
   refresh = false;
 }

 void displace(int i) {
   xAcelTotal_1 = 0;
   yAcelTotal_1 = 0;    
   zAcelTotal_1 = 0;    
   product = 0;  
   for (int j = 0; j <= bodies.length-1; j++) {  //j is the index of all the other bodies.
     if (i != j) {                //i is the index for *this* body.
       xDiff = bodies[j].xpos - this.xpos;
       yDiff = bodies[j].ypos - this.ypos;
       zDiff = bodies[j].zpos - this.zpos;        
       dSq = ((xDiff)*(xDiff) + (yDiff)*(yDiff) + (zDiff)*(zDiff));  
       gD = G/dSq;
       product = bodies[j].mass*gD;  
       xAcel[j] = product * xDiff;
       yAcel[j] = product * yDiff;
       zAcel[j] = product * zDiff;        
       xAcelTotal_1 = xAcelTotal_1 + xAcel[j];
       yAcelTotal_1 = yAcelTotal_1 + yAcel[j];
       zAcelTotal_1 = zAcelTotal_1 + zAcel[j];
     }
   }

   //leapfrog
   this.xpos = this.xpos + xVel + (0.5 * xAcelTotal_1 * time * time);
   this.ypos = this.ypos + yVel + (0.5 * yAcelTotal_1 * time * time);
   this.zpos = this.zpos + zVel + (0.5 * zAcelTotal_1 * time * time);
   this.xVel = this.xVel + (0.5 * xAcelTotal_0 + xAcelTotal_1) * time;
   this.yVel = this.yVel + (0.5 * yAcelTotal_0 + yAcelTotal_1) * time;
   this.zVel = this.zVel + (0.5 * zAcelTotal_0 + zAcelTotal_1) * time;
   objFill = int(constrain(zpos, 0, 240));  
   
   //history:
   xHist[hist-1] = this.xpos;
   yHist[hist-1] = this.ypos;
   zHist[hist-1] = this.zpos;
   for (int j = 0; j < hist-1; j++) {
     xHist[j] = xHist[j+1];
     yHist[j] = yHist[j+1];
     zHist[j] = zHist[j+1];      
   }  
   xAcelTotal_0 = xAcelTotal_1;
   yAcelTotal_0 = yAcelTotal_1;      
   zAcelTotal_0 = zAcelTotal_1;          
 }    
}

Page Index Toggle Pages: 1