LK
YaBB Newbies
Offline
Posts: 7
Toronto
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; } }