// // 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 // // ------------------------------------------------------------------------- // // Data file handling // static const char id[]="$Id$"; #include "config.h" #include #include #define RAD(x) ((x)*(M_PI/180.0)) // ---------------------------------------- CONSTRUCTION/DESTRUCTION // Config::Config() { int f; m_error=""; for(f=0;f& mass) { static struct { Command cmd; string token; int val; } enum_list[]= { {enable_cmd,"solid",static_cast(solid)}, {enable_cmd,"lighting",static_cast(lighting)}, {enable_cmd,"texture",static_cast(texture)}, {collide_cmd,"none",static_cast(none)}, {collide_cmd,"merge",static_cast(merge)}, {collide_cmd,"delta_merge",static_cast(delta_merge)}, {collide_cmd,"shatter",static_cast(shatter)}, {plane_cmd,"xy",static_cast(xy_plane)}, {plane_cmd,"xz",static_cast(xz_plane)}, {plane_cmd,"yz",static_cast(yz_plane)}, {cmd_error,"",0} }; Mass parent; Mass *nm; Command cmd; vector arg; ifstream file(fname.c_str()); bool found; int f; vector::size_type idx; vector::size_type sidx; if (!file) { m_error="File not found : " + fname; return false; } try { while(getCommand(file,cmd,arg)) { switch(cmd) { case enable_cmd: f=0; found=false; while(enum_list[f].token!="") { if (enum_list[f].cmd==enable_cmd && CompareNoCase(enum_list[f].token,arg[0])) { found=true; m_flag[static_cast(enum_list[f].val)]=true; break; } f++; } if (!found) { m_error="Illegal argument to enable : " + arg[0]; throw m_error; } break; case disable_cmd: f=0; found=false; while(enum_list[f].token!="") { if (enum_list[f].cmd==enable_cmd && CompareNoCase(enum_list[f].token,arg[0])) { found=true; m_flag[static_cast(enum_list[f].val)]=false; break; } f++; } if (!found) { m_error="Illegal argument to disable : " + arg[0]; throw m_error; } break; case collide_cmd: f=0; found=false; while(enum_list[f].token!="") { if (enum_list[f].cmd==collide_cmd && CompareNoCase(enum_list[f].token,arg[0])) { found=true; m_collide=static_cast(enum_list[f].val); break; } f++; } if (!found) { m_error="Illegal argument to collide : " + arg[0]; throw m_error; } break; case const_cmd: m_const=toDouble(arg[0]); break; case body_cmd: nm= new Mass (arg[0], toDouble(arg[1]), m_scale, toDouble(arg[2]), toDouble(arg[3]), toDouble(arg[4]), toDouble(arg[5]), toDouble(arg[6]), toDouble(arg[7]), toGLfloat(arg[8]), toGLfloat(arg[9]), toGLfloat(arg[10]), toDouble(arg[11])); if (mass.size()(enum_list[f].val); break; } f++; } if (!found) { m_error="Illegal argument to plane : " + arg[0]; throw m_error; } break; case shatter_cmd: m_s_no=toInt(arg[0]); m_s_delta=toDouble(arg[1]); m_s_min=toDouble(arg[2]); m_s_max=toDouble(arg[3]); m_s_shield=toInt(arg[4]); break; case scale_cmd: m_scale=toDouble(arg[0]); break; case look_at_cmd: found=false; for(sidx=0;sidx& l) const { l=m_look; } bool Config::particlesDefined() const { return m_particles; } void Config::getParticles(GLfloat& alpha_dec, GLfloat& alpha_min, GLfloat& size ) const { alpha_dec=m_p_adec; alpha_min=m_p_amin; size=m_p_size; } void Config::getLookAndTravel(int& look, int &travel) const { look=m_look_at; travel=m_travel_as; } void Config::getShatter(int& num, double& delta, double& min_mass, double& max_mass, int& shield) const { num=m_s_no; delta=m_s_delta; min_mass=m_s_min; max_mass=m_s_max; shield=m_s_shield; } bool Config::sparksDefined() const { return m_sparks; } void Config::getSparks(int& num, GLfloat& alpha_dec, GLfloat& alpha_min, int& length, GLfloat& delta) const { num=m_sp_no; alpha_dec=m_sp_adec; alpha_min=m_sp_amin; length=m_sp_length; delta=m_sp_delta; } size_t Config::maxMass() const { return m_max_mass; } void Config::getFog(GLfloat& dist, GLfloat& r, GLfloat& g, GLfloat& b, bool& fog_light) { dist=m_fog_dist; r=m_fog_r; g=m_fog_g; b=m_fog_b; fog_light=m_fog_light; } void Config::windowSize(int& w, int& h) const { w=m_winw; h=m_winh; } string Config::error() const { return m_error; } // ---------------------------------------- PRIVATE MEMBERS // bool Config::CompareNoCase(const string& s1, const string& s2) { const char *p1,*p2; p1=s1.c_str(); p2=s2.c_str(); while((*p1)&&(tolower(*p1)==tolower(*p2))) { p1++; p2++; } if (tolower(*p1)-tolower(*p2)) return false; else return true; } Config::GetWordStatus Config::getWord(ifstream& file, string& word, const string& ignore, const string& term) { bool done=false; bool in_word=false; bool in_comment=false; string not_allowed; char c; if (term==";") not_allowed=","; else if (term==",") not_allowed=";"; else not_allowed=",;"; word=""; while(!done) { file.get(c); if (file.eof()) return GWEof; if (in_comment) { if (c=='\n') in_comment=false; } else { if (c=='#') in_comment=true; else if (in_word) { bool at_term=(term.find(c)!=string::npos); bool in_error=(not_allowed.find(c)!=string::npos); if (in_error) { if (term==",") return GWTooFewArgs; else if (term==";") return GWTooManyArgs; else return GWSyntax; } if (at_term) done=true; else if (c!='\n') word+=c; } else { bool in_ignore=(ignore.find(c)!=string::npos); if (!in_ignore) { word+=c; in_word=true; } } } } return GWOK; } bool Config::getCommand(ifstream& file, Config::Command& cmd, vector& arg) { static struct { string cmd; Command token; int args; } cmd_list[]= { {"enable",enable_cmd,1}, {"disable",disable_cmd,1}, {"collide",collide_cmd,1}, {"const",const_cmd,1}, {"body",body_cmd,12}, {"radial",radial_cmd,10}, {"light",light_cmd,4}, {"camera",camera_cmd,4}, {"look",look_cmd,1}, {"texture",texture_cmd,4}, {"num_texture",num_texture_cmd,1}, {"reuse",reuse_cmd,2}, {"particles",particles_cmd,3}, {"shatter",shatter_cmd,5}, {"multiple",multiple_cmd,15}, {"mreuse",mreuse_cmd,3}, {"plane",plane_cmd,1}, {"scale",scale_cmd,1}, {"look_at",look_at_cmd,1}, {"travel_as",travel_as_cmd,1}, {"window_size",window_size_cmd,2}, {"sparks",sparks_cmd,5}, {"max_mass",max_mass_cmd,1}, {"mlook",mlook_cmd,2}, {"ring",ring_cmd,9}, {"mring",mring_cmd,10}, {"ring_texture",ring_texture_cmd,4}, {"ring_reuse",ring_reuse_cmd,2}, {"ring_mreuse",ring_mreuse_cmd,3}, {"fog",fog_cmd,5}, {"",cmd_error,1} }; string word; string cmd_string; int expect; int f; switch (getWord(file,word," \t\n"," \t\n")) { case GWEof: cmd=cmd_eof; return false; case GWSyntax: m_error="Syntax error in command " + word; return false; default: break; } f=0; cmd=cmd_error; while(cmd_list[f].cmd!="") { if (CompareNoCase(cmd_list[f].cmd,word)) { cmd_string=word; cmd=cmd_list[f].token; expect=cmd_list[f].args; break; } f++; } if (cmd==cmd_error) { m_error="Unrecognised command " + word; return false; } arg.clear(); for(f=0;f(toDouble(s)); } int Config::toInt(const string& s) { int i; char *p; i=static_cast(strtol(s.c_str(),&p,0)); if (*p) { m_error="Invalid integer : " + s; throw m_error; } return i; } size_t Config::toSize(const string& s) { size_t i; char *p; i=static_cast(strtol(s.c_str(),&p,0)); if (*p) { m_error="Invalid integer : " + s; throw m_error; } return i; } bool Config::toYesNo(const string& s) { if (s!="yes" && s!="no") { m_error="Invalid yes/no : " + s; throw m_error; } return s=="yes"; } bool Config::bindTexture(const string& name, int w, int h, GLuint id) { FILE *fp; ifstream file(name.c_str()); GLubyte *mem; int x,y; if (!(fp=fopen(name.c_str(),"r"))) { m_error="file " + name + " not found"; return false; } mem=new GLubyte[w*h*3]; for(y=0;y=0;x--) { mem[x*3+y*w*3]=fgetc(fp); mem[x*3+y*w*3+1]=fgetc(fp); mem[x*3+y*w*3+2]=fgetc(fp); if (feof(fp)) { fclose(fp); m_error="file " + name + " to short"; delete[] mem; return false; } } fclose(fp); glBindTexture(GL_TEXTURE_2D,id); glTexImage2D(GL_TEXTURE_2D,0,3,w,h,0,GL_RGB,GL_UNSIGNED_BYTE,mem); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); delete[] mem; return true; } void Config::genRadial(Mass **newMass, const Mass& parent, const string& name, double mass, double dist, double ang, double spd, GLfloat r, GLfloat g, GLfloat b, double rot) { double px,py,pz; double pdx,pdy,pdz; double ox,oy,oz; double dx,dy,dz; parent.getPosition(px,py,pz); parent.getDelta(pdx,pdy,pdz); switch(m_plane) { case xy_plane: ox=px+dist*sin(ang); oy=py-dist*cos(ang); oz=pz; ang+=RAD(90); dx=spd*sin(ang); dy=-spd*cos(ang); dz=0.0; break; case xz_plane: ox=px+dist*sin(ang); oy=py; oz=pz-dist*cos(ang); ang+=RAD(90); dx=spd*sin(ang); dy=0.0; dz=-spd*cos(ang); break; case yz_plane: ox=px; oy=py+dist*sin(ang); oz=pz-dist*cos(ang); ang+=RAD(90); dx=0.0; dy=spd*sin(ang); dz=-spd*cos(ang); break; default: m_error="INTERNAL ERROR: invalid plane defined"; throw m_error; } dx+=pdx; dy+=pdy; dz+=pdz; *newMass=new Mass(name, mass, m_scale, ox,oy,oz, dx,dy,dz, r,g,b,rot); } string Config::makeName(string& name, int no) { char s[1024]; string n; sprintf(s,"%s %d",name.c_str(),no); n=s; return n; } // END OF FILE //