From 99778e9b85bd4a16a9055587a273446068577100 Mon Sep 17 00:00:00 2001 From: Ian C Date: Tue, 2 May 2006 19:12:46 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. --- glgrav.cpp | 955 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 955 insertions(+) create mode 100644 glgrav.cpp (limited to 'glgrav.cpp') diff --git a/glgrav.cpp b/glgrav.cpp new file mode 100644 index 0000000..3586e7d --- /dev/null +++ b/glgrav.cpp @@ -0,0 +1,955 @@ +// +// glgrav - OpenGL N-Body gravity simulator +// +// Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.co.uk) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// ------------------------------------------------------------------------- +// +// Main +// +static const char id[]="$Id$"; + +#include "global.h" +#include "config.h" +#include "mass.h" +#include "particles.h" +#include "sparks.h" + +#include +#include + +static Config config; +static vector mass; +static Particles *particles=0; +static Sparks *sparks=0; + +static int win; +static int width=100; +static int height=100; +static GLfloat particleSize=1.0f; + +#define MENU_SOLID 1 +#define MENU_LIGHTING 2 +#define MENU_TEXTURE 3 +#define MENU_PARTICLES 4 +#define MENU_SPARKS 5 +#define MENU_FOG 6 +#define MENU_RESETPOS 7 +#define MENU_QUIT 8 +#define LOOK_NONE -1 + +#define MENU_TRAVEL 1000 +#define MENU_LOOK 2000 +#define MENU_FRAME_SKIP 3000 + +static int menu; +static int travel_menu; +static int look_menu; +static int frame_skip_menu; + +#ifdef DEBUG + +#define DBG_DUMPOBJ 1 +static int debug_menu; +static void DebugMenu(int item); +#endif + +static bool solid; +static bool light; +static bool texture; +static bool render_particles; +static bool render_sparks; +static vector look; +static int travel_as=LOOK_NONE; +static int look_at=LOOK_NONE; +static int frame_skip=0; +static int frame=0; +static bool fog=false; +static bool fog_light=false; +static GLfloat fog_col[4]={0.0f,0.0f,0.0f,1.0f}; + +static struct + { + GLfloat x,y,z; + GLfloat ang; + GLfloat speed; + } camera={0.0f,0.0f,0.0f,0.0f,0.0f}; + +static struct + { + int mx,my; + bool lmb; + bool shift; + bool ctrl; + bool pgup; + bool pgdn; + } control; + +static void Reshape(int w,int h); +static void Mouse(int b,int s, int x, int y); +static void Move(int x, int y); +static void Display(void); +static void Update(void); +static void Menu(int item); +static void TravelMenu(int item); +static void LookMenu(int item); +static void FrameSkipMenu(int item); +static void Key(int key, int mx, int my); + +static void HandleCollision(Config::Collide collide, + vector& del,vector& mv, + Mass& m1, Mass& m2, int idx1, int idx2); +static void SetOption(int opt, string text, bool flag); +static void GLPrint(char *fmt,...); + + +int main(int argc, char *argv[]) +{ + int f; + + srand(time(0)); + + // Init GLUT display. Note window is created here to be reshaped later + // as it appears necessary for textures to work! + // + glutInit(&argc,argv); + glutInitWindowSize(width,height); + glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); + + win=glutCreateWindow(argv[0]); + + + // Program initialisation + // + mass.clear(); + + if (!config.read(argc == 2 ? argv[1] : "dat",mass)) + { + cerr << "Config file reading failed : \n" << config.error() << endl; + exit(1); + } + + config.getCamera(camera.x,camera.y,camera.z,camera.ang); + + solid=config.enabled(Config::solid); + light=config.enabled(Config::lighting); + texture=config.enabled(Config::texture); + config.look(look); + config.getLookAndTravel(look_at,travel_as); + fog=config.enabled(Config::fog); + + if (config.particlesDefined()) + { + GLfloat adec,amin; + + config.getParticles(adec,amin,particleSize); + particles=new Particles(adec,amin); + render_particles=true; + } + else + render_particles=false; + + if (config.sparksDefined()) + { + int num,len; + GLfloat adec,amin,delta; + + config.getSparks(num,adec,amin,len,delta); + sparks=new Sparks(num,adec,amin,len,delta); + render_sparks=true; + } + else + render_sparks=false; + + config.windowSize(width,height); + + width=max(width,100); + height=max(height,100); + +# ifdef DEBUG + { + vector::size_type f; + + for(f=0;f::size_type li; + + travel_menu=glutCreateMenu(TravelMenu); + glutAddMenuEntry("None",MENU_TRAVEL+LOOK_NONE); + + look_menu=glutCreateMenu(LookMenu); + glutAddMenuEntry("None",MENU_LOOK+LOOK_NONE); + + for(li=0;li::size_type f; + + switch (item) + { + case DBG_DUMPOBJ: + for(f=0;f(camera.x), + static_cast(camera.y), + static_cast(camera.z), + x,y,z, + 0.0,1.0,0.0); + } + else + { + glRotatef(360.0-camera.ang,0.0f,1.0f,0.0f); + glTranslatef(-camera.x,-camera.y,-camera.z); + } +} + + +static void DrawMasses(Mass::DrawItem item) +{ + vector::const_iterator i; + Mass lm; + + for(i=mass.begin();i!=mass.end();i++) + { + SetView(); + + if (light) + { + GLfloat light[4]; + GLfloat pos[4]; + string name; + + name=config.light(light); + + if (name!=i->getName() && findMass(mass,name,lm)) + { + double x,y,z; + + lm.getPosition(x,y,z); + + pos[0]=static_cast(x); + pos[1]=static_cast(y); + pos[2]=static_cast(z); + pos[3]=1.0f; + + glLightfv(GL_LIGHT1,GL_DIFFUSE,light); + glLightfv(GL_LIGHT1,GL_POSITION,pos); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT1); + + if (fog) + glEnable(GL_FOG); + } + else + { + if (!fog_light) + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + } + } + + i->draw(solid,texture,item); + } +} + + +static void Display(void) +{ + Mass lm; + + /* Looking up/down doesn't work yet... + */ + if ((travel_as!=LOOK_NONE)&&(findMass(mass,look[travel_as],lm))) + { + double x,y,z; + + lm.getPosition(x,y,z); + + camera.x=static_cast(x); + camera.y=static_cast(y); + camera.z=static_cast(z); + } + else + { + GLPrint("Pos: %d,%d,%d",(int)camera.x,(int)camera.y,(int)camera.z); + GLPrint("Angle: %d",(int)camera.ang); + } + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + if (fog) + glEnable(GL_FOG); + else + glDisable(GL_FOG); + + DrawMasses(Mass::eMass); + + glEnable(GL_BLEND); + + DrawMasses(Mass::eRing); + + glDisable(GL_LIGHT1); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + + if (fog) + glEnable(GL_FOG); + + if (particles && render_particles) + { + glPointSize(particleSize); + particles->draw(); + } + + if (sparks && render_sparks) + { + glPointSize(1); + sparks->draw(); + } + + glDisable(GL_BLEND); + + glFlush(); + glutSwapBuffers(); +} + + +static void Shatter(vector& mv, Mass& m,int no,double delta,int shield) +{ + double px,py,pz; + double npx,npy,npz; + double dx,dy,dz; + double ndx,ndy,ndz; + GLfloat r,g,b; + int f; + string name; + bool texture; + GLuint id; + double nm; + int size; + + nm=m.getMass()/no; + m.getDelta(dx,dy,dz); + m.getPosition(px,py,pz); + size=static_cast(m.getSize()); + m.getColour(r,g,b); + name=m.getName(); + texture=m.getTexture(id); + + for(f=0;f& del,vector& mv, + Mass& m1, Mass& m2, int idx1, int idx2) +{ + Mass *win; + Mass *lose; + double merge_mass; + double dx,dy,dz; + double odx,ody,odz; + int no; + double delta,min,max; + int shield; + + switch(collide) + { + case Config::merge: + if (m1.getMass()>=m2.getMass()) + { + win=&m1; + lose=&m2; + del[idx2]=true; + } + else + { + win=&m2; + lose=&m1; + del[idx1]=true; + } + + merge_mass=win->getMass()+lose->getMass(); + + win->reset(merge_mass); + + if (sparks) + { + double x1,y1,z1; + double x2,y2,z2; + + m1.getPosition(x1,y1,z1); + m2.getPosition(x2,y2,z2); + + sparks->add(x1+(x2-x1)/2, + y1+(y2-y1)/2, + z1+(z2-z1)/2); + } + + break; + + case Config::delta_merge: + if (m1.getMass()>=m2.getMass()) + { + win=&m1; + lose=&m2; + del[idx2]=true; + } + else + { + win=&m2; + lose=&m1; + del[idx1]=true; + } + + win->getDelta(odx,ody,odz); + lose->getDelta(dx,dy,dz); + + odx+=dx*(lose->getMass()/win->getMass()); + ody+=dy*(lose->getMass()/win->getMass()); + odz+=dz*(lose->getMass()/win->getMass()); + + merge_mass=win->getMass()+lose->getMass(); + + win->reset(merge_mass,odx,ody,odz); + + if (sparks) + { + double x1,y1,z1; + double x2,y2,z2; + + m1.getPosition(x1,y1,z1); + m2.getPosition(x2,y2,z2); + + sparks->add(x1+(x2-x1)/2, + y1+(y2-y1)/2, + z1+(z2-z1)/2); + } + + break; + + case Config::shatter: + config.getShatter(no,delta,min,max,shield); + + if (m1.getMass()=max) || + (m2.getMass()=max)) + { + HandleCollision(Config::merge,del,mv,m1,m2,idx1,idx2); + return; + } + + Shatter(mv,m1,no,delta,shield); + Shatter(mv,m2,no,delta,shield); + + if (sparks) + { + double x1,y1,z1; + double x2,y2,z2; + + m1.getPosition(x1,y1,z1); + m2.getPosition(x2,y2,z2); + + sparks->add(x1+(x2-x1)/2, + y1+(y2-y1)/2, + z1+(z2-z1)/2); + } + + del[idx1]=true; + del[idx2]=true; + + break; + + case Config::none: + break; + + default: + break; + } +} + + +static void Update(void) +{ + vector new_mass; + vector del_mass; + vector::size_type f,r; + GLfloat mva; + + new_mass=mass; + + for(f=0;fmass.size() || !del_mass[f]) + mass.push_back(new_mass[f]); + + for(f=0;fadd(static_cast(x), + static_cast(y), + static_cast(z), + static_cast(px), + static_cast(py), + static_cast(pz), + r,g,b); + } + + mva=(control.mx-(width/2))/(100.0f*width/800.0); + + if (mva<-0.5 || mva>0.5) + { + camera.ang-=mva; + + if (camera.ang<0.0) + camera.ang+=360.0; + else if (camera.ang>=360.0) + camera.ang-=360.0; + } + + if (control.pgup) + camera.y+=10; + + if (control.pgdn) + camera.y-=10; + + control.pgup=false; + control.pgdn=false; + + if (control.lmb) + { + if (camera.speed<20.0) + camera.speed+=0.5; + + if (control.ctrl) + camera.speed*=10; + + if (control.shift) + { + camera.x+=(GLfloat)(sin(camera.ang*M_PI/180.0)*camera.speed); + camera.z+=(GLfloat)(cos(camera.ang*M_PI/180.0)*camera.speed); + } + else + { + camera.x-=(GLfloat)(sin(camera.ang*M_PI/180.0)*camera.speed); + camera.z-=(GLfloat)(cos(camera.ang*M_PI/180.0)*camera.speed); + } + + if (control.ctrl) + camera.speed/=10; + } + else + { + if (camera.speed>0.0) + camera.speed-=0.5; + + if (camera.speed<0.0) + camera.speed+=0.5; + } + + frame++; + + if (sparks) + sparks->update(); + + if (particles) + particles->update(); + + if (!frame_skip || (frame%frame_skip)==0) + glutPostWindowRedisplay(win); +} + + +static void GLPrint(char *fmt,...) +{ + char s[256]; + va_list va; + char *p; + + va_start(va,fmt); + vsprintf(s,fmt,va); + + p=s; + + /* + while(*p) + glutBitmapCharacter(GLUT_BITMAP_8_BY_13,(int)*p++); + */ +} + + +// END OF FILE // -- cgit v1.2.3