summaryrefslogtreecommitdiff
path: root/glgrav.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'glgrav.cpp')
-rw-r--r--glgrav.cpp955
1 files changed, 955 insertions, 0 deletions
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 <cstdarg>
+#include <ctime>
+
+static Config config;
+static vector<Mass> 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<string> 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<bool>& del,vector<Mass>& 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<Mass>::size_type f;
+
+ for(f=0;f<mass.size();f++)
+ cout << "Initial : " << mass[f] << endl;
+ }
+# endif
+
+ glutDisplayFunc(Display);
+ glutMouseFunc(Mouse);
+ glutMotionFunc(Move);
+ glutPassiveMotionFunc(Move);
+ glutReshapeFunc(Reshape);
+ glutSpecialFunc(Key);
+ glutIdleFunc(Update);
+
+ // Menu initialisation
+ //
+ menu=glutCreateMenu(Menu);
+ glutAddMenuEntry("X",MENU_SOLID);
+ glutAddMenuEntry("X",MENU_LIGHTING);
+ glutAddMenuEntry("X",MENU_TEXTURE);
+ glutAddMenuEntry("X",MENU_PARTICLES);
+ glutAddMenuEntry("X",MENU_SPARKS);
+ glutAddMenuEntry("X",MENU_FOG);
+ glutAddMenuEntry("Reset Position",MENU_RESETPOS);
+
+ SetOption(MENU_SOLID,"Solid",solid);
+ SetOption(MENU_LIGHTING,"Lighting",light);
+ SetOption(MENU_TEXTURE,"Textures",texture);
+ SetOption(MENU_PARTICLES,"Particles",render_particles);
+ SetOption(MENU_SPARKS,"Sparks",render_sparks);
+ SetOption(MENU_FOG,"Fog",fog);
+
+ // Create look and travel menus
+ //
+ vector<string>::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<look.size();li++)
+ {
+ glutSetMenu(travel_menu);
+ glutAddMenuEntry(look[li].c_str(),MENU_TRAVEL+li);
+ glutSetMenu(look_menu);
+ glutAddMenuEntry(look[li].c_str(),MENU_LOOK+li);
+ }
+
+ // Create frame skip menu
+ //
+ frame_skip_menu=glutCreateMenu(FrameSkipMenu);
+
+ for(f=0;f<20;f++)
+ {
+ char s[64];
+ int skip;
+
+ if (f)
+ {
+ skip=f+1;
+ sprintf(s,"Draw every %d frames",skip);
+ }
+ else
+ {
+ skip=f;
+ strcpy(s,"No frame skip");
+ }
+
+ glutAddMenuEntry(s,MENU_FRAME_SKIP+skip);
+ }
+
+ glutSetMenu(menu);
+ glutAddSubMenu("Travel as",travel_menu);
+ glutAddSubMenu("Look at",look_menu);
+ glutAddSubMenu("Frame skip",frame_skip_menu);
+ glutAddMenuEntry("Quit",MENU_QUIT);
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+
+ // Create optional debug menu
+ //
+# ifdef DEBUG
+ {
+ debug_menu=glutCreateMenu(DebugMenu);
+ glutAddMenuEntry("Dump Objects",DBG_DUMPOBJ);
+ glutSetMenu(menu);
+ glutAddSubMenu("DEBUG",debug_menu);
+ }
+# endif
+
+ // Open GL initialisation
+ //
+ glShadeModel(GL_SMOOTH);
+
+ if (!light)
+ glDisable(GL_LIGHTING);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_POINT_SMOOTH);
+
+ glClearColor(0.0f,0.0f,0.0f,1.0);
+
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+ if (fog)
+ {
+ GLfloat dist;
+
+ config.getFog(dist,fog_col[0],fog_col[1],fog_col[2],fog_light);
+
+ glFogfv(GL_FOG_COLOR,fog_col);
+ glFogf(GL_FOG_START,0.0f);
+ glFogf(GL_FOG_END,dist);
+ glFogi(GL_FOG_MODE,GL_LINEAR);
+
+ glClearColor(fog_col[0],fog_col[1],fog_col[2],1.0);
+ }
+
+ // Enter the main loop
+ //
+ glutReshapeWindow(width,height);
+ glutMainLoop();
+
+ return EXIT_SUCCESS;
+}
+
+
+static void Reshape(int w,int h)
+{
+ width=w;
+ height=h;
+
+ glViewport(0,0,w,h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,1.0f,100000.0f);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+
+static void Mouse(int b,int s, int x, int y)
+{
+ int mod=glutGetModifiers();
+
+ if (b==GLUT_LEFT_BUTTON)
+ {
+ control.lmb=(s==GLUT_DOWN);
+
+ control.shift=mod&GLUT_ACTIVE_SHIFT;
+ control.ctrl=mod&GLUT_ACTIVE_CTRL;
+ }
+}
+
+
+static void Move(int x,int y)
+{
+ control.mx=x;
+ control.my=y;
+}
+
+
+static void Menu(int item)
+{
+#ifdef DEBUG
+ cout << "Menu(" << item << ")\n";
+#endif
+
+ switch (item)
+ {
+ case MENU_SOLID:
+ solid=!solid;
+ SetOption(MENU_SOLID,"Solid",solid);
+ break;
+
+ case MENU_LIGHTING:
+ light=!light;
+ SetOption(MENU_LIGHTING,"Lighting",light);
+
+ if (!light)
+ glDisable(GL_LIGHTING);
+ break;
+
+ case MENU_TEXTURE:
+ texture=!texture;
+ SetOption(MENU_TEXTURE,"Texture",texture);
+ break;
+
+ case MENU_RESETPOS:
+ config.getCamera(camera.x,camera.y,camera.z,camera.ang);
+ break;
+
+ case MENU_PARTICLES:
+ render_particles=!render_particles;
+ SetOption(MENU_PARTICLES,"Particles",render_particles);
+ break;
+
+ case MENU_SPARKS:
+ render_sparks=!render_sparks;
+ SetOption(MENU_SPARKS,"Sparks",render_sparks);
+ break;
+
+ case MENU_FOG:
+ if (config.enabled(Config::fog))
+ {
+ fog=!fog;
+ SetOption(MENU_FOG,"Fog",fog);
+
+ if (fog)
+ glClearColor(fog_col[0],fog_col[1],fog_col[2],1.0);
+ else
+ glClearColor(0.0f,0.0f,0.0f,1.0);
+ }
+ break;
+
+ case MENU_QUIT:
+ exit(EXIT_SUCCESS);
+ break;
+ }
+}
+
+
+static void TravelMenu(int item)
+{
+#ifdef DEBUG
+ cout << "TravelMenu(" << item << ")\n";
+#endif
+
+ int old=travel_as;
+
+ travel_as=item-MENU_TRAVEL;
+
+ if (travel_as!=LOOK_NONE and look_at==travel_as)
+ travel_as=old;
+}
+
+
+static void LookMenu(int item)
+{
+#ifdef DEBUG
+ cout << "LookMenu(" << item << ")\n";
+#endif
+
+ int old=look_at;
+
+ look_at=item-MENU_LOOK;
+
+ if (look_at!=LOOK_NONE and look_at==travel_as)
+ look_at=old;
+}
+
+
+static void FrameSkipMenu(int item)
+{
+#ifdef DEBUG
+ cout << "FrameSkipMenu(" << item << ")\n";
+#endif
+
+ frame_skip=item-MENU_FRAME_SKIP;
+}
+
+
+#ifdef DEBUG
+static void DebugMenu(int item)
+{
+ vector<Mass>::size_type f;
+
+ switch (item)
+ {
+ case DBG_DUMPOBJ:
+ for(f=0;f<mass.size();f++)
+ cout << mass[f] << endl;
+ break;
+ }
+}
+#endif
+
+
+static void SetOption(int opt, string text, bool flag)
+{
+ if (flag)
+ text+=" Off";
+ else
+ text+=" On";
+
+ glutChangeToMenuEntry(opt,text.c_str(),opt);
+}
+
+
+static void Key(int key, int mx, int my)
+{
+ switch(key)
+ {
+ case GLUT_KEY_PAGE_DOWN:
+ control.pgdn=true;
+ break;
+
+ case GLUT_KEY_PAGE_UP:
+ control.pgup=true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static void SetView()
+{
+ Mass lm;
+
+ glLoadIdentity();
+
+ if ((look_at!=LOOK_NONE)&&(findMass(mass,look[look_at],lm)))
+ {
+ double x,y,z;
+
+ lm.getPosition(x,y,z);
+
+ // TODO: The last parameters (0,1,0) are the UP vector, and need
+ // some calculating to prevent awkward looking 'flips'
+ //
+ gluLookAt(static_cast<GLdouble>(camera.x),
+ static_cast<GLdouble>(camera.y),
+ static_cast<GLdouble>(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<Mass>::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<GLfloat>(x);
+ pos[1]=static_cast<GLfloat>(y);
+ pos[2]=static_cast<GLfloat>(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<GLfloat>(x);
+ camera.y=static_cast<GLfloat>(y);
+ camera.z=static_cast<GLfloat>(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<Mass>& 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<int>(m.getSize());
+ m.getColour(r,g,b);
+ name=m.getName();
+ texture=m.getTexture(id);
+
+ for(f=0;f<no;f++)
+ if (mv.size()<config.maxMass())
+ {
+ npx=px+RND(size*2)-size;
+ npy=py+RND(size*2)-size;
+ npz=pz+RND(size*2)-size;
+
+ if (npx<px)
+ ndx=dx-DRand()*delta;
+ else
+ ndx=dx+DRand()*delta;
+
+ if (npy<py)
+ ndy=dy-DRand()*delta;
+ else
+ ndy=dy+DRand()*delta;
+
+ if (npz<pz)
+ ndz=dz-DRand()*delta;
+ else
+ ndz=dz+DRand()*delta;
+
+ Mass m(name,nm,config.scale(),
+ npx,npy,npz,ndx,ndy,ndz,r,g,b,0.5,shield);
+
+ if (texture)
+ m.setTexture(id);
+
+ mv.push_back(m);
+ }
+
+}
+
+
+static void HandleCollision(Config::Collide collide,
+ vector<bool>& del,vector<Mass>& 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()<min || m2.getMass()<min)
+ {
+ HandleCollision(Config::merge,del,mv,m1,m2,idx1,idx2);
+ return;
+ }
+
+ if ((m1.getMass()<max && m2.getMass()>=max) ||
+ (m2.getMass()<max && m1.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<Mass> new_mass;
+ vector<bool> del_mass;
+ vector<Mass>::size_type f,r;
+ GLfloat mva;
+
+ new_mass=mass;
+
+ for(f=0;f<mass.size();f++)
+ del_mass.push_back(false);
+
+ for(f=0;f<mass.size();f++)
+ for(r=0;r<mass.size();r++)
+ if (f!=r && !del_mass[f] && !del_mass[r])
+ if (new_mass[f].calcAttraction(mass[r],config.gravConst()))
+ HandleCollision
+ (config.collide(),
+ del_mass,new_mass,new_mass[f],mass[r],f,r);
+
+ mass.clear();
+
+ for(f=0;f<new_mass.size();f++)
+ if (f>mass.size() || !del_mass[f])
+ mass.push_back(new_mass[f]);
+
+ for(f=0;f<mass.size();f++)
+ {
+ GLfloat r,g,b;
+ double x,y,z;
+ double px,py,pz;
+
+ mass[f].move();
+
+ mass[f].getColour(r,g,b);
+ mass[f].getPosition(x,y,z);
+ mass[f].getPreviousPosition(px,py,pz);
+
+ if (particles && !mass[f].isMassless())
+ particles->add(static_cast<GLfloat>(x),
+ static_cast<GLfloat>(y),
+ static_cast<GLfloat>(z),
+ static_cast<GLfloat>(px),
+ static_cast<GLfloat>(py),
+ static_cast<GLfloat>(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 //