diff options
author | Ian C <ianc@noddybox.co.uk> | 2010-08-18 14:38:34 +0000 |
---|---|---|
committer | Ian C <ianc@noddybox.co.uk> | 2010-08-18 14:38:34 +0000 |
commit | 19bbd5822593c7198dd54eb0f5d38fa1ed8d8fb7 (patch) | |
tree | 97f7f8849c3a8282ba571a64ff2a655cdf5d41aa | |
parent | 0d2f672482fee91a9642a7cb6eb01fcdded79159 (diff) |
Reformatted code and altered the attraction rule to something a bit more
correct. Also added two tests to prove it works.
-rw-r--r-- | camera.h | 42 | ||||
-rw-r--r-- | config.cpp | 647 | ||||
-rw-r--r-- | config.h | 212 | ||||
-rw-r--r-- | glgrav.cpp | 298 | ||||
-rw-r--r-- | makefile | 6 | ||||
-rw-r--r-- | mass.cpp | 142 | ||||
-rw-r--r-- | mass.h | 188 | ||||
-rw-r--r-- | matrix.h | 74 | ||||
-rw-r--r-- | particles.cpp | 12 | ||||
-rw-r--r-- | particles.h | 44 | ||||
-rw-r--r-- | sparks.cpp | 20 | ||||
-rw-r--r-- | sparks.h | 50 | ||||
-rw-r--r-- | test1.dat | 51 | ||||
-rw-r--r-- | test2.dat | 53 |
14 files changed, 1073 insertions, 766 deletions
@@ -31,27 +31,27 @@ #include "matrix.h" class Camera - { - public: - Camera(); - virtual ~Camera(); - - // Initially the camera always looks along the Z axis - // - void setPos(GLfloat x, GLfloat y, GLfloat z); - - void addSpeed(GLfloat speed); - void roll(double angle); - void pitch(double angle); - - void setView() const; - - private: - GLfloat px,py,pz; - Matrix direction; - Matrix left; - Matrix up; - }; +{ +public: + Camera(); + virtual ~Camera(); + + // Initially the camera always looks along the Z axis + // + void setPos(GLfloat x, GLfloat y, GLfloat z); + + void addSpeed(GLfloat speed); + void roll(double angle); + void pitch(double angle); + + void setView() const; + +private: + GLfloat px,py,pz; + Matrix direction; + Matrix left; + Matrix up; +}; #endif @@ -36,60 +36,66 @@ Config::Config() { int f; - m_error=""; + m_error = ""; for(f=0;f<num_flags;f++) - m_flag[f]=false; + { + m_flag[f] = false; + } - m_collide=none; + m_collide = none; - m_light=""; - m_lr=m_lg=m_lb=1.0f; + m_light = ""; + m_lr = 1.0f; + m_lg = 1.0f; + m_lb = 1.0f; - m_const=0.0; + m_const = 0.0; - m_x=0.0f; - m_y=0.0f; - m_z=0.0f; - m_yaw=0.0f; + m_x = 0.0f; + m_y = 0.0f; + m_z = 0.0f; + m_yaw = 0.0f; - m_glid=0; - m_glid_no=0; - m_glid_idx=0; + m_glid = 0; + m_glid_no = 0; + m_glid_idx = 0; - m_scale=1.0; + m_scale = 1.0; - m_particles=false; + m_particles = false; - m_plane=xy_plane; + m_plane = xy_plane; - m_look_at=-1; - m_travel_as=-1; + m_look_at = -1; + m_travel_as = -1; - m_s_no=10; - m_s_delta=5.0; - m_s_min=10.0; - m_s_max=1000.0; - m_s_shield=100; + m_s_no = 10; + m_s_delta = 5.0; + m_s_min = 10.0; + m_s_max = 1000.0; + m_s_shield = 100; - m_sparks=false; + m_sparks = false; - m_winw=640; - m_winh=480; + m_winw = 640; + m_winh = 480; - m_max_mass=1000000; + m_max_mass = 1000000; - m_fog_dist=0.0f; - m_fog_r=0.0f; - m_fog_g=0.0f; - m_fog_b=0.0f; - m_fog_light=false; + m_fog_dist = 0.0f; + m_fog_r = 0.0f; + m_fog_g = 0.0f; + m_fog_b = 0.0f; + m_fog_light = false; } Config::~Config() { if (m_glid) + { delete[] m_glid; + } } @@ -98,24 +104,24 @@ Config::~Config() bool Config::read(const string& fname,vector<Mass>& mass) { static struct - { + { Command cmd; string token; int val; - } enum_list[]= - { - {enable_cmd,"solid",static_cast<int>(solid)}, - {enable_cmd,"lighting",static_cast<int>(lighting)}, - {enable_cmd,"texture",static_cast<int>(texture)}, - {collide_cmd,"none",static_cast<int>(none)}, - {collide_cmd,"merge",static_cast<int>(merge)}, - {collide_cmd,"delta_merge",static_cast<int>(delta_merge)}, - {collide_cmd,"shatter",static_cast<int>(shatter)}, - {plane_cmd,"xy",static_cast<int>(xy_plane)}, - {plane_cmd,"xz",static_cast<int>(xz_plane)}, - {plane_cmd,"yz",static_cast<int>(yz_plane)}, - {cmd_error,"",0} - }; + } enum_list[]= + { + {enable_cmd,"solid",static_cast<int>(solid)}, + {enable_cmd,"lighting",static_cast<int>(lighting)}, + {enable_cmd,"texture",static_cast<int>(texture)}, + {collide_cmd,"none",static_cast<int>(none)}, + {collide_cmd,"merge",static_cast<int>(merge)}, + {collide_cmd,"delta_merge",static_cast<int>(delta_merge)}, + {collide_cmd,"shatter",static_cast<int>(shatter)}, + {plane_cmd,"xy",static_cast<int>(xy_plane)}, + {plane_cmd,"xz",static_cast<int>(xz_plane)}, + {plane_cmd,"yz",static_cast<int>(yz_plane)}, + {cmd_error,"",0} + }; Mass parent; Mass *nm; @@ -128,37 +134,37 @@ bool Config::read(const string& fname,vector<Mass>& mass) vector<string>::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<Flag>(enum_list[f].val)]=true; break; - } - f++; } + f++; + } if (!found) - { + { m_error="Illegal argument to enable : " + arg[0]; throw m_error; - } + } break; @@ -166,22 +172,22 @@ bool Config::read(const string& fname,vector<Mass>& mass) 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<Flag>(enum_list[f].val)]=false; break; - } - f++; } + f++; + } if (!found) - { + { m_error="Illegal argument to disable : " + arg[0]; throw m_error; - } + } break; @@ -189,22 +195,22 @@ bool Config::read(const string& fname,vector<Mass>& mass) 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<Collide>(enum_list[f].val); break; - } - f++; } + f++; + } if (!found) - { + { m_error="Illegal argument to collide : " + arg[0]; throw m_error; - } + } break; @@ -222,14 +228,16 @@ bool Config::read(const string& fname,vector<Mass>& mass) toGLfloat(arg[10]), toDouble(arg[11])); if (mass.size()<m_max_mass) + { mass.push_back(*nm); + } delete nm; break; case radial_cmd: if (findMass(mass,arg[2],parent)) - { + { genRadial(&nm,parent, arg[0],toDouble(arg[1]), toDouble(arg[3]),RAD(toDouble(arg[4])), @@ -239,20 +247,22 @@ bool Config::read(const string& fname,vector<Mass>& mass) toDouble(arg[9])); if (mass.size()<m_max_mass) + { mass.push_back(*nm); + } delete nm; - } + } else - { + { m_error="Unknown parent in radial : " + arg[2]; throw m_error; - } + } break; case multiple_cmd: if (findMass(mass,arg[4],parent)) - { + { string name=arg[0]; int num=toInt(arg[1]); double ms=toDouble(arg[2]); @@ -271,7 +281,7 @@ bool Config::read(const string& fname,vector<Mass>& mass) int f; for(f=0;f<num;f++) - { + { genRadial(&nm,parent, makeName(name,f+1),ms, dist,ang,spd, @@ -284,16 +294,18 @@ bool Config::read(const string& fname,vector<Mass>& mass) spd+=spd_i; if (mass.size()<m_max_mass) + { mass.push_back(*nm); + } delete nm; - } } + } else - { + { m_error="Unknown parent in multiple : " + arg[4]; throw m_error; - } + } break; case light_cmd: @@ -312,34 +324,36 @@ bool Config::read(const string& fname,vector<Mass>& mass) case look_cmd: if (findMass(mass,arg[0],parent)) + { m_look.push_back(arg[0]); + } else - { + { m_error="Unknown object in look : " + arg[0]; throw m_error; - } + } break; case mlook_cmd: { - int num=toInt(arg[1]); - string name=arg[0]; - int f; + int num=toInt(arg[1]); + string name=arg[0]; + int f; - for(f=0;f<num;f++) + for(f=0;f<num;f++) { - string ss; + string ss; - ss=makeName(name,f+1); + ss=makeName(name,f+1); - if (findMass(mass,ss,idx)) + if (findMass(mass,ss,idx)) { - m_look.push_back(ss); + m_look.push_back(ss); } - else + else { - m_error="Unknown object in mlook : " + ss; - throw m_error; + m_error="Unknown object in mlook : " + ss; + throw m_error; } } } @@ -347,42 +361,44 @@ bool Config::read(const string& fname,vector<Mass>& mass) case texture_cmd: if (!m_glid) - { + { m_error="texture used without preceeding num_texture"; throw m_error; - } + } if (findMass(mass,arg[0],idx)) - { + { if (m_glid_no==m_glid_idx) - { + { m_error="more textures than expected"; throw m_error; - } + } GLuint id=m_glid[m_glid_idx++]; if (bindTexture(arg[1],toInt(arg[2]),toInt(arg[3]),id)) + { mass[idx].setTexture(id); + } else - { + { m_error="Failed to bind texture : " + m_error; throw m_error; - } } + } else - { + { m_error="Unknown object in texture : " + arg[0]; throw m_error; - } + } break; case num_texture_cmd: if (m_glid) - { + { m_error="num_texture used more than once"; throw m_error; - } + } m_glid_no=toInt(arg[0]); m_glid=new GLuint[m_glid_no]; @@ -392,76 +408,80 @@ bool Config::read(const string& fname,vector<Mass>& mass) case reuse_cmd: if (findMass(mass,arg[0],idx)) - { + { if (findMass(mass,arg[1],parent)) - { + { GLuint id; if (parent.getTexture(id) || parent.getRingTexture(id)) + { mass[idx].setTexture(id); + } else - { + { m_error="reuse object has no texture : " + arg[1]; throw m_error; - } } + } else - { + { m_error="Unknown object in reuse : " + arg[1]; throw m_error; - } } + } else - { + { m_error="Unknown object in reuse : " + arg[0]; throw m_error; - } + } break; case mreuse_cmd: if (findMass(mass,arg[2],parent)) - { + { int num=toInt(arg[1]); string name=arg[0]; int f; for(f=0;f<num;f++) - { + { string ss=makeName(name,f+1); if (findMass(mass,ss,idx)) - { + { GLuint id; if (parent.getTexture(id) || parent.getRingTexture(id)) + { mass[idx].setTexture(id); + } else - { + { m_error="mreuse object has no texture : " + arg[2]; throw m_error; - } } + } else - { + { m_error="Unknown object in mreuse : " + ss; throw m_error; - } } } + } else - { + { m_error="Unknown object in mreuse : " + arg[2]; throw m_error; - } + } break; case ring_cmd: if (findMass(mass,arg[0],idx)) - { + { mass[idx].setRing(toDouble(arg[1]),toDouble(arg[2]), toGLfloat(arg[3]), toGLfloat(arg[4]), @@ -469,38 +489,39 @@ bool Config::read(const string& fname,vector<Mass>& mass) toGLfloat(arg[6]), toDouble(arg[7]), toDouble(arg[8])); - } + } else - { + { m_error="Unknown object in ring : " + arg[0]; throw m_error; - } + } break; case mring_cmd: { - int num=toInt(arg[1]); - string name=arg[0]; - int f; + int num=toInt(arg[1]); + string name=arg[0]; + int f; - for(f=0;f<num;f++) + for(f=0;f<num;f++) { - string ss=makeName(name,f+1); + string ss=makeName(name,f+1); - if (findMass(mass,ss,idx)) + if (findMass(mass,ss,idx)) { - mass[idx].setRing(toDouble(arg[2]),toDouble(arg[3]), - toGLfloat(arg[4]), - toGLfloat(arg[5]), - toGLfloat(arg[6]), - toGLfloat(arg[7]), - toDouble(arg[8]), - toDouble(arg[9])); + mass[idx].setRing(toDouble(arg[2]), + toDouble(arg[3]), + toGLfloat(arg[4]), + toGLfloat(arg[5]), + toGLfloat(arg[6]), + toGLfloat(arg[7]), + toDouble(arg[8]), + toDouble(arg[9])); } - else + else { - m_error="Unknown object in mring : " + ss; - throw m_error; + m_error="Unknown object in mring : " + ss; + throw m_error; } } } @@ -508,103 +529,103 @@ bool Config::read(const string& fname,vector<Mass>& mass) case ring_texture_cmd: if (!m_glid) - { + { m_error="ring used without preceeding num_texture"; throw m_error; - } + } if (findMass(mass,arg[0],idx)) - { + { if (m_glid_no==m_glid_idx) - { + { m_error="more textures than expected"; throw m_error; - } + } GLuint id=m_glid[m_glid_idx++]; if (bindTexture(arg[1],toInt(arg[2]),toInt(arg[3]),id)) mass[idx].setRingTexture(id); else - { + { m_error="Failed to bind texture : " + m_error; throw m_error; - } } + } else - { + { m_error="Unknown object in ring : " + arg[0]; throw m_error; - } + } break; case ring_reuse_cmd: if (findMass(mass,arg[0],idx)) - { + { if (findMass(mass,arg[1],parent)) - { + { GLuint id; if (parent.getRingTexture(id) || - parent.getTexture(id)) + parent.getTexture(id)) mass[idx].setRingTexture(id); else - { + { m_error="ring_reuse object has no texture : " + - arg[1]; + arg[1]; throw m_error; - } } + } else - { + { m_error="Unknown object in ring_reuse : " + arg[1]; throw m_error; - } } + } else - { + { m_error="Unknown object in ring_reuse : " + arg[0]; throw m_error; - } + } break; case ring_mreuse_cmd: if (findMass(mass,arg[2],parent)) - { + { int num=toInt(arg[1]); string name=arg[0]; int f; for(f=0;f<num;f++) - { + { string ss=makeName(name,f+1); if (findMass(mass,ss,idx)) - { + { GLuint id; if (parent.getRingTexture(id) || - parent.getTexture(id)) + parent.getTexture(id)) mass[idx].setRingTexture(id); else - { + { m_error="ring_mreuse object has " - "no texture : " + arg[2]; + "no texture : " + arg[2]; throw m_error; - } } + } else - { + { m_error="Unknown object in ring_mreuse : " + ss; throw m_error; - } } } + } else - { + { m_error="Unknown object in ring_mreuse : " + arg[2]; throw m_error; - } + } break; case particles_cmd: @@ -618,22 +639,22 @@ bool Config::read(const string& fname,vector<Mass>& mass) f=0; found=false; while(enum_list[f].token!="") - { + { if (enum_list[f].cmd==plane_cmd && CompareNoCase(enum_list[f].token,arg[0])) - { + { found=true; m_plane=static_cast<Plane>(enum_list[f].val); break; - } - f++; } + f++; + } if (!found) - { + { m_error="Illegal argument to plane : " + arg[0]; throw m_error; - } + } break; @@ -653,34 +674,36 @@ bool Config::read(const string& fname,vector<Mass>& mass) found=false; for(sidx=0;sidx<m_look.size();sidx++) - if (m_look[sidx]==arg[0]) - { + if (m_look[sidx]==arg[0]) + { m_look_at=sidx; found=true; - } + } if (!found) - { + { m_error="Illegal argument to look_at : " + arg[0]; throw m_error; - } + } break; case travel_as_cmd: found=false; for(sidx=0;sidx<m_look.size();sidx++) - if (m_look[sidx]==arg[0]) - { + { + if (m_look[sidx]==arg[0]) + { m_travel_as=sidx; found=true; - } + } + } if (!found) - { + { m_error="Illegal argument to travel_as : " + arg[0]; throw m_error; - } + } break; case window_size_cmd: @@ -712,22 +735,24 @@ bool Config::read(const string& fname,vector<Mass>& mass) default: break; - } } } + } catch(...) - { + { file.close(); return false; - } + } if (cmd==cmd_eof) - { + { file.close(); return true; - } + } else + { return false; + } } void Config::getCamera(GLfloat& x, GLfloat& y, GLfloat& z, GLfloat& yaw) const @@ -858,15 +883,19 @@ bool Config::CompareNoCase(const string& s1, const string& s2) p2=s2.c_str(); while((*p1)&&(tolower(*p1)==tolower(*p2))) - { + { p1++; p2++; - } + } if (tolower(*p1)-tolower(*p2)) + { return false; + } else + { return true; + } } @@ -880,64 +909,84 @@ Config::GetWordStatus Config::getWord(ifstream& file, string& word, 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; + { + 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; - } + { + 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 (at_term) - done=true; - else - if (c!='\n') - word+=c; + if (in_error) + { + if (term==",") + { + return GWTooFewArgs; } - else + else if (term==";") { - bool in_ignore=(ignore.find(c)!=string::npos); - - if (!in_ignore) - { - word+=c; - in_word=true; - } + 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; } @@ -947,44 +996,44 @@ bool Config::getCommand(ifstream& file, Config::Command& cmd, vector<string>& 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 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; @@ -992,7 +1041,7 @@ bool Config::getCommand(ifstream& file, Config::Command& cmd, int f; switch (getWord(file,word," \t\n"," \t\n")) - { + { case GWEof: cmd=cmd_eof; return false; @@ -1001,40 +1050,40 @@ bool Config::getCommand(ifstream& file, Config::Command& cmd, 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; - } + return false; + } arg.clear(); for(f=0;f<expect;f++) - { + { string error; switch (getWord(file,word," \t\n",(f==expect-1) ? ";" : ",")) - { + { case GWOK: - break; + break; case GWTooManyArgs: cmd=cmd_error; @@ -1055,10 +1104,10 @@ bool Config::getCommand(ifstream& file, Config::Command& cmd, cmd=cmd_error; m_error="Syntax error in " + cmd_string; return false; - } + } arg.push_back(word); - } + } return true; } @@ -1071,10 +1120,10 @@ double Config::toDouble(const string& s) r=strtod(s.c_str(),&p); if (*p) - { + { m_error="Invalid floating point number : " + s; - throw m_error; - } + throw m_error; + } return r; } @@ -1094,10 +1143,10 @@ int Config::toInt(const string& s) i=static_cast<int>(strtol(s.c_str(),&p,0)); if (*p) - { + { m_error="Invalid integer : " + s; - throw m_error; - } + throw m_error; + } return i; } @@ -1111,10 +1160,10 @@ size_t Config::toSize(const string& s) i=static_cast<size_t>(strtol(s.c_str(),&p,0)); if (*p) - { + { m_error="Invalid integer : " + s; - throw m_error; - } + throw m_error; + } return i; } @@ -1123,10 +1172,10 @@ size_t Config::toSize(const string& s) bool Config::toYesNo(const string& s) { if (s!="yes" && s!="no") - { + { m_error="Invalid yes/no : " + s; throw m_error; - } + } return s=="yes"; } @@ -1140,28 +1189,30 @@ bool Config::bindTexture(const string& name, int w, int h, GLuint id) int x,y; if (!(fp=fopen(name.c_str(),"r"))) - { + { m_error="file " + name + " not found"; - return false; - } + return false; + } mem=new GLubyte[w*h*3]; for(y=0;y<h;y++) - for(x=w-1;x>=0;x--) - { + { + for(x=w-1;x>=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); @@ -1189,7 +1240,7 @@ void Config::genRadial(Mass **newMass, const Mass& parent, parent.getDelta(pdx,pdy,pdz); switch(m_plane) - { + { case xy_plane: ox=px+dist*sin(ang); oy=py-dist*cos(ang); @@ -1223,7 +1274,7 @@ void Config::genRadial(Mass **newMass, const Mass& parent, default: m_error="INTERNAL ERROR: invalid plane defined"; throw m_error; - } + } dx+=pdx; dy+=pdy; @@ -32,142 +32,148 @@ #include "mass.h" class Config - { - public: - enum Flag {solid, lighting, texture, fog, num_flags}; - enum Collide {none, merge, delta_merge, shatter}; +{ +public: + enum Flag {solid, lighting, texture, fog, num_flags}; + enum Collide {none, merge, delta_merge, shatter}; - Config(); - virtual ~Config(); + Config(); + virtual ~Config(); - // Note that the vector is added to. It must be cleared beforehand - // if required. - // - bool read(const string& file, vector<Mass>& mass); + // Note that the vector is added to. It must be cleared beforehand + // if required. + // + bool read(const string& file, vector<Mass>& mass); - void getCamera(GLfloat& x, GLfloat& y, GLfloat& z, GLfloat& yaw) const; + void getCamera(GLfloat& x, GLfloat& y, GLfloat& z, GLfloat& yaw) const; - bool enabled(Flag flag) const; - Collide collide() const; - string light(GLfloat v[4]) const; - double gravConst() const; - double scale() const; + bool enabled(Flag flag) const; + Collide collide() const; + string light(GLfloat v[4]) const; + double gravConst() const; + double scale() const; - void windowSize(int& w,int& h) const; + void windowSize(int& w,int& h) const; - void getShatter(int& num, double& delta, - double& min_mass, double& max_mass, - int& shield) const; + void getShatter(int& num, double& delta, + double& min_mass, double& max_mass, + int& shield) const; - bool sparksDefined() const; + bool sparksDefined() const; - void getSparks(int& num, GLfloat& alpha_dec, GLfloat& alpha_min, - int& length, GLfloat& delta) const; + void getSparks(int& num, GLfloat& alpha_dec, GLfloat& alpha_min, + int& length, GLfloat& delta) const; - size_t maxMass() const; + size_t maxMass() const; - // Args set to -1 if undefined - // - void getLookAndTravel(int& look, int &travel) const; + // Args set to -1 if undefined + // + void getLookAndTravel(int& look, int &travel) const; - bool particlesDefined() const; + bool particlesDefined() const; - void getParticles(GLfloat& alpha_dec, GLfloat& alpha_min, - GLfloat& size) const; + void getParticles(GLfloat& alpha_dec, GLfloat& alpha_min, + GLfloat& size) const; - void getFog(GLfloat& dist, GLfloat& r, GLfloat& g, GLfloat& b, - bool& fog_light); + void getFog(GLfloat& dist, GLfloat& r, GLfloat& g, GLfloat& b, + bool& fog_light); - void look(vector<string>& l) const; + void look(vector<string>& l) const; - string error() const; + string error() const; - private: - enum Plane {xy_plane, xz_plane, yz_plane}; +private: + enum Plane {xy_plane, xz_plane, yz_plane}; - Plane m_plane; + Plane m_plane; - string m_error; - bool m_flag[num_flags]; - Collide m_collide; - double m_const; - GLfloat m_x,m_y,m_z,m_pitch,m_yaw; + string m_error; + bool m_flag[num_flags]; + Collide m_collide; + double m_const; + GLfloat m_x; + GLfloat m_y; + GLfloat m_z; + GLfloat m_pitch; + GLfloat m_yaw; - double m_scale; + double m_scale; - string m_light; - GLfloat m_lr,m_lg,m_lb; + string m_light; + GLfloat m_lr; + GLfloat m_lg; + GLfloat m_lb; - vector<string> m_look; - int m_look_at; - int m_travel_as; + vector<string> m_look; + int m_look_at; + int m_travel_as; - bool m_particles; - GLfloat m_p_adec; - GLfloat m_p_amin; - GLfloat m_p_size; + bool m_particles; + GLfloat m_p_adec; + GLfloat m_p_amin; + GLfloat m_p_size; - GLuint *m_glid; - int m_glid_no; - int m_glid_idx; + GLuint *m_glid; + int m_glid_no; + int m_glid_idx; - int m_s_no; - double m_s_delta; - double m_s_min; - double m_s_max; - int m_s_shield; + int m_s_no; + double m_s_delta; + double m_s_min; + double m_s_max; + int m_s_shield; - bool m_sparks; - int m_sp_no; - GLfloat m_sp_adec; - GLfloat m_sp_amin; - int m_sp_length; - GLfloat m_sp_delta; + bool m_sparks; + int m_sp_no; + GLfloat m_sp_adec; + GLfloat m_sp_amin; + int m_sp_length; + GLfloat m_sp_delta; - int m_winw; - int m_winh; + int m_winw; + int m_winh; - size_t m_max_mass; + size_t m_max_mass; - GLfloat m_fog_dist; - GLfloat m_fog_r; - GLfloat m_fog_g; - GLfloat m_fog_b; - bool m_fog_light; + GLfloat m_fog_dist; + GLfloat m_fog_r; + GLfloat m_fog_g; + GLfloat m_fog_b; + bool m_fog_light; - enum Command {enable_cmd, disable_cmd, collide_cmd, const_cmd, - body_cmd, radial_cmd, light_cmd, camera_cmd, look_cmd, - texture_cmd, num_texture_cmd, reuse_cmd, particles_cmd, - shatter_cmd, multiple_cmd, mreuse_cmd, plane_cmd, - scale_cmd, look_at_cmd, travel_as_cmd, window_size_cmd, - sparks_cmd, max_mass_cmd, mlook_cmd, - ring_cmd, mring_cmd, ring_texture_cmd, ring_reuse_cmd, - ring_mreuse_cmd, fog_cmd, - cmd_eof, cmd_error}; + enum Command {enable_cmd, disable_cmd, collide_cmd, const_cmd, + body_cmd, radial_cmd, light_cmd, camera_cmd, look_cmd, + texture_cmd, num_texture_cmd, reuse_cmd, particles_cmd, + shatter_cmd, multiple_cmd, mreuse_cmd, plane_cmd, + scale_cmd, look_at_cmd, travel_as_cmd, window_size_cmd, + sparks_cmd, max_mass_cmd, mlook_cmd, + ring_cmd, mring_cmd, ring_texture_cmd, ring_reuse_cmd, + ring_mreuse_cmd, fog_cmd, + cmd_eof, cmd_error}; - enum GetWordStatus {GWOK, GWEof, GWSyntax, - GWTooFewArgs, GWTooManyArgs}; + enum GetWordStatus {GWOK, GWEof, GWSyntax, + GWTooFewArgs, GWTooManyArgs}; - bool CompareNoCase(const string& s1, const string& s2); - GetWordStatus getWord(ifstream& fp, string& word, - const string& ignore, const string& term); - bool getCommand(ifstream& fp, Command& cmd, vector<string>& val); + bool CompareNoCase(const string& s1, const string& s2); + GetWordStatus getWord(ifstream& fp, string& word, + const string& ignore, const string& term); + bool getCommand(ifstream& fp, Command& cmd, vector<string>& val); - void 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); + void 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 toDouble(const string& s); - GLfloat toGLfloat(const string& s); - int toInt(const string& s); - size_t toSize(const string& s); - bool toYesNo(const string& s); - - bool bindTexture(const string& name, int w, int h, GLuint id); - - string makeName(string& name, int no); - }; + double toDouble(const string& s); + GLfloat toGLfloat(const string& s); + int toInt(const string& s); + size_t toSize(const string& s); + bool toYesNo(const string& s); + + bool bindTexture(const string& name, int w, int h, GLuint id); + + string makeName(string& name, int no); +}; #endif @@ -84,21 +84,21 @@ 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}; +{ + 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; +{ + 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); @@ -139,10 +139,10 @@ int main(int argc, char *argv[]) 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); @@ -154,41 +154,45 @@ int main(int argc, char *argv[]) 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); + 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 - { +#ifdef DEBUG + { vector<Mass>::size_type f; for(f=0;f<mass.size();f++) cout << "Initial : " << mass[f] << endl; - } -# endif + } +#endif glutDisplayFunc(Display); glutMouseFunc(Mouse); @@ -227,35 +231,35 @@ int main(int argc, char *argv[]) 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); @@ -266,21 +270,23 @@ int main(int argc, char *argv[]) // Create optional debug menu // -# ifdef DEBUG - { +#ifdef DEBUG + { debug_menu=glutCreateMenu(DebugMenu); glutAddMenuEntry("Dump Objects",DBG_DUMPOBJ); glutSetMenu(menu); glutAddSubMenu("DEBUG",debug_menu); - } -# endif + } +#endif // Open GL initialisation // glShadeModel(GL_SMOOTH); if (!light) - glDisable(GL_LIGHTING); + { + glDisable(GL_LIGHTING); + } glEnable(GL_DEPTH_TEST); glEnable(GL_COLOR_MATERIAL); @@ -292,7 +298,7 @@ int main(int argc, char *argv[]) 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); @@ -303,7 +309,7 @@ int main(int argc, char *argv[]) glFogi(GL_FOG_MODE,GL_LINEAR); glClearColor(fog_col[0],fog_col[1],fog_col[2],1.0); - } + } // Enter the main loop // @@ -332,12 +338,12 @@ 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; - } + } } @@ -355,7 +361,7 @@ static void Menu(int item) #endif switch (item) - { + { case MENU_SOLID: solid=!solid; SetOption(MENU_SOLID,"Solid",solid); @@ -366,7 +372,9 @@ static void Menu(int item) SetOption(MENU_LIGHTING,"Lighting",light); if (!light) + { glDisable(GL_LIGHTING); + } break; case MENU_TEXTURE: @@ -390,21 +398,25 @@ static void Menu(int item) 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; - } + } } @@ -419,7 +431,9 @@ static void TravelMenu(int item) travel_as=item-MENU_TRAVEL; if (travel_as!=LOOK_NONE and look_at==travel_as) + { travel_as=old; + } } @@ -434,7 +448,9 @@ static void LookMenu(int item) look_at=item-MENU_LOOK; if (look_at!=LOOK_NONE and look_at==travel_as) + { look_at=old; + } } @@ -454,12 +470,14 @@ 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 @@ -467,9 +485,13 @@ static void DebugMenu(int item) static void SetOption(int opt, string text, bool flag) { if (flag) + { text+=" Off"; + } else + { text+=" On"; + } glutChangeToMenuEntry(opt,text.c_str(),opt); } @@ -478,7 +500,7 @@ static void SetOption(int opt, string text, bool flag) static void Key(int key, int mx, int my) { switch(key) - { + { case GLUT_KEY_PAGE_DOWN: control.pgdn=true; break; @@ -489,7 +511,7 @@ static void Key(int key, int mx, int my) default: break; - } + } } @@ -500,7 +522,7 @@ static void SetView() glLoadIdentity(); if ((look_at!=LOOK_NONE)&&(findMass(mass,look[look_at],lm))) - { + { double x,y,z; lm.getPosition(x,y,z); @@ -513,12 +535,12 @@ static void SetView() 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); - } + } } @@ -528,11 +550,11 @@ static void DrawMasses(Mass::DrawItem item) Mass lm; for(i=mass.begin();i!=mass.end();i++) - { + { SetView(); if (light) - { + { GLfloat light[4]; GLfloat pos[4]; string name; @@ -540,7 +562,7 @@ static void DrawMasses(Mass::DrawItem item) name=config.light(light); if (name!=i->getName() && findMass(mass,name,lm)) - { + { double x,y,z; lm.getPosition(x,y,z); @@ -557,17 +579,17 @@ static void DrawMasses(Mass::DrawItem item) if (fog) glEnable(GL_FOG); - } + } else - { + { if (!fog_light) glDisable(GL_FOG); glDisable(GL_LIGHTING); - } } + } i->draw(solid,texture,item); - } + } } @@ -575,10 +597,10 @@ static void Display(void) { Mass lm; - /* Looking up/down doesn't work yet... - */ + // 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); @@ -586,19 +608,23 @@ static void Display(void) 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); @@ -611,19 +637,21 @@ static void Display(void) 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(); - } + sparks->draw(); + } glDisable(GL_BLEND); @@ -655,35 +683,51 @@ static void Shatter(vector<Mass>& mv, Mass& m,int no,double delta,int shield) 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); - } + } + } } @@ -702,27 +746,27 @@ static void HandleCollision(Config::Collide collide, 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; @@ -730,25 +774,25 @@ static void HandleCollision(Config::Collide collide, m2.getPosition(x2,y2,z2); sparks->add(x1+(x2-x1)/2, - y1+(y2-y1)/2, - z1+(z2-z1)/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); @@ -762,7 +806,7 @@ static void HandleCollision(Config::Collide collide, win->reset(merge_mass,odx,ody,odz); if (sparks) - { + { double x1,y1,z1; double x2,y2,z2; @@ -770,9 +814,9 @@ static void HandleCollision(Config::Collide collide, m2.getPosition(x2,y2,z2); sparks->add(x1+(x2-x1)/2, - y1+(y2-y1)/2, - z1+(z2-z1)/2); - } + y1+(y2-y1)/2, + z1+(z2-z1)/2); + } break; @@ -780,23 +824,23 @@ static void HandleCollision(Config::Collide collide, 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; @@ -804,9 +848,9 @@ static void HandleCollision(Config::Collide collide, m2.getPosition(x2,y2,z2); sparks->add(x1+(x2-x1)/2, - y1+(y2-y1)/2, - z1+(z2-z1)/2); - } + y1+(y2-y1)/2, + z1+(z2-z1)/2); + } del[idx1]=true; del[idx2]=true; @@ -818,7 +862,7 @@ static void HandleCollision(Config::Collide collide, default: break; - } + } } @@ -832,24 +876,38 @@ static void Update(void) 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; @@ -861,6 +919,7 @@ static void Update(void) 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), @@ -868,70 +927,95 @@ static void Update(void) 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); + } } @@ -38,14 +38,14 @@ HEADERS = global.h \ OBJECTS = $(SOURCES:.cpp=.o) -# NOTE1: Use these libs for GNU/linux. They should work with any unix that has -# X11 too. +# NOTE1: Use these libs for GNU/linux. They should give a head-start to any +# UNIX that has X11/OpenGL. # #LIBS = -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -lXext -lXi -lXmu -lm LIBS = -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -lXext -lm -# NOTE2: Use thes libs for cygwin +# NOTE2: Use thes libs for cygwin -- currently broken # #LIBS = -lglut32 -lglu32 -lopengl32 @@ -69,9 +69,9 @@ Mass::Mass() Mass::Mass(const string& name, double mass, double scale, - double posx, double posy, double posz, - double dx, double dy, double dz, - GLfloat r, GLfloat g, GLfloat b, double rot, int shield) + double posx, double posy, double posz, + double dx, double dy, double dz, + GLfloat r, GLfloat g, GLfloat b, double rot, int shield) { m_name=name; @@ -97,12 +97,14 @@ Mass::Mass(const string& name, double mass, double scale, m_shield=shield; if (m_mass<=0.0) - { - m_mass=0.0001; + { + m_mass=0.0001; m_massless=true; - } + } else - m_massless=false; + { + m_massless=false; + } m_ring=false; m_ring_textured=false; @@ -126,8 +128,8 @@ Mass::~Mass() // ---------------------------------------- PUBLIC MEMBERS // void Mass::setRing(double from, double to, - GLfloat r, GLfloat g, GLfloat b, GLfloat alpha, - double rot, double ang) + GLfloat r, GLfloat g, GLfloat b, GLfloat alpha, + double rot, double ang) { m_ring=true; m_ring_from=from; @@ -159,10 +161,10 @@ bool Mass::getTexture(GLuint& id) const void Mass::setRingTexture(GLuint id) { if (m_ring) - { + { m_ring_textured=true; m_ring_id=id; - } + } } @@ -238,12 +240,14 @@ void Mass::reset(double mass, double dx, double dy, double dz) m_dz=dz; if (m_mass<=0.0) - { - m_mass=0.0001; + { + m_mass=0.0001; m_massless=true; - } + } else - m_massless=false; + { + m_massless=false; + } } @@ -253,12 +257,14 @@ void Mass::reset(double mass) calcSize(); if (m_mass<=0.0) - { - m_mass=0.0001; + { + m_mass=0.0001; m_massless=true; - } + } else - m_massless=false; + { + m_massless=false; + } } @@ -270,37 +276,59 @@ bool Mass::calcAttraction(Mass& m, double gr_const) double dx,dy,dz; if (m.m_massless) - return false; + { + return false; + } dist=calcDistance2(m,dx,dy,dz); if (dist==0.0) - return !m_massless; + { + return !m_massless; + } if (dist<(m_size + m.m_size) && (m_shield==0 || m.m_shield==0)) - collide=true; + { + collide=true; + } else - collide=false; + { + collide=false; + } + + // ga=((gr_const*m.m_mass)*(gr_const*m_mass))/(dist*gr_const); - ga=((gr_const*m.m_mass)*(gr_const*m_mass))/(dist*gr_const); + ga=gr_const * (m_mass / dist); if (m_x<m.m_x) + { m_dx+=ga/(m_mass/dx); + } if (m_x>m.m_x) + { m_dx-=ga/(m_mass/dx); + } if (m_y<m.m_y) + { m_dy+=ga/(m_mass/dy); + } if (m_y>m.m_y) + { m_dy-=ga/(m_mass/dy); + } if (m_z<m.m_z) + { m_dz+=ga/(m_mass/dz); + } if (m_z>m.m_z) + { m_dz-=ga/(m_mass/dz); + } return collide && !m_massless; } @@ -320,7 +348,9 @@ void Mass::move() m_ring_ang+=m_ring_rot; if (m_shield) - m_shield--; + { + m_shield--; + } } @@ -330,7 +360,7 @@ void Mass::draw(bool solid, bool texture, Mass::DrawItem item) const GLUquadric *q; if (m_massless && item==eMass) - { + { GLboolean l=glIsEnabled(GL_LIGHTING); glDisable(GL_LIGHTING); @@ -340,65 +370,79 @@ void Mass::draw(bool solid, bool texture, Mass::DrawItem item) const glEnd(); if (l) + { glEnable(GL_LIGHTING); } + } else - { + { // Render the object // if (item==eMass && (q=gluNewQuadric())) - { + { glColor4f(m_r,m_g,m_b,1.0f); glTranslated(m_x,m_y,m_z); if (!solid) + { gluQuadricDrawStyle(q,GLU_LINE); + } gluQuadricNormals(q,GLU_SMOOTH); if (m_textured && texture && solid) - { + { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,m_texture_id); gluQuadricTexture(q,1); - } + } else + { glDisable(GL_TEXTURE_2D); + } if (m_ang!=0.0) + { glRotated(m_ang,0.0,1.0,0.0); + } glRotated(90.0,1.0,0.0,0.0); gluSphere(q,m_size,sp,sp); gluDeleteQuadric(q); - } + } // Render the ring (if present) // if (m_ring && item==eRing && (q=gluNewQuadric())) - { + { glColor4f(m_rr,m_rg,m_rb,m_ring_alpha); glTranslated(m_x,m_y,m_z); if (!solid) + { gluQuadricDrawStyle(q,GLU_LINE); + } gluQuadricNormals(q,GLU_SMOOTH); if (m_ring_textured && texture && solid) - { + { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,m_ring_id); gluQuadricTexture(q,1); - } + } else + { glDisable(GL_TEXTURE_2D); + } glRotated(m_ring_tilt,1.0,0.0,0.0); if (m_ring_ang!=0.0) + { glRotated(-m_ring_ang,0.0,0.0,1.0); + } gluDisk(q,m_size*m_ring_from,m_size*m_ring_to,sp,1); @@ -409,8 +453,8 @@ void Mass::draw(bool solid, bool texture, Mass::DrawItem item) const gluDisk(q,m_size*m_ring_from,m_size*m_ring_to,sp,1); gluDeleteQuadric(q); - } } + } } @@ -432,7 +476,9 @@ void Mass::calcSize() m_size=pow(m_size,0.333333333333333333333)*m_scale; if (m_size<1.0) - m_size=1.0; + { + m_size=1.0; + } } @@ -441,13 +487,13 @@ void Mass::calcSize() ostream& operator<<(ostream& os, const Mass& m) { os << "Name " << m.m_name << " (mass " << m.m_mass - << ", size " << m.m_size << ", shield " << m.m_shield << ")" << endl - << " P (" << m.m_x << ", " << m.m_y << ", " << m.m_z << ")" << endl - << " D (" << m.m_dx << ", " << m.m_dy << ", " << m.m_dz << ")" << endl - << " R (" << m.m_rot << ", " << m.m_ang << ")" << endl - << " T (" << m.m_textured << ", " << m.m_texture_id << ")" << endl - << " Ring (" << m.m_ring << ", " << m.m_ring_from - << ", " << m.m_ring_to << ")" << endl; + << ", size " << m.m_size << ", shield " << m.m_shield << ")" << endl + << " P (" << m.m_x << ", " << m.m_y << ", " << m.m_z << ")" << endl + << " D (" << m.m_dx << ", " << m.m_dy << ", " << m.m_dz << ")" << endl + << " R (" << m.m_rot << ", " << m.m_ang << ")" << endl + << " T (" << m.m_textured << ", " << m.m_texture_id << ")" << endl + << " Ring (" << m.m_ring << ", " << m.m_ring_from + << ", " << m.m_ring_to << ")" << endl; return os; } @@ -458,11 +504,13 @@ bool findMass(vector<Mass>& m, const string& name, Mass& ret) vector<Mass>::const_iterator i; for(i=m.begin();i!=m.end();i++) + { if (i->getName()==name) - { + { ret=*i; return true; - } + } + } return false; } @@ -470,8 +518,12 @@ bool findMass(vector<Mass>& m, const string& name, Mass& ret) bool findMass(vector<Mass>& m, const string& name, vector<Mass>::size_type& i) { for(i=0;i<m.size();i++) + { if (m[i].getName()==name) + { return true; + } + } return false; } @@ -30,100 +30,100 @@ #include "global.h" class Mass - { - public: - enum DrawItem {eMass, eRing}; - - Mass(); - Mass(const string& name, double mass, double scale, - double posx, double posy, double posz, - double dx, double dy, double dz, - GLfloat r, GLfloat g, GLfloat b, - double rot, int sheild=0); - virtual ~Mass(); - - // Define a ring - // - void setRing(double from, double to, - GLfloat r, GLfloat g, GLfloat b, GLfloat alpha, - double rot, double angle); - - // Set up an Open GL texture ID to use. It is assumed that - // texturing is not used till this member is called. - // - // The get function returns true if a texture has been assigned. - // - void setTexture(GLuint id); - bool getTexture(GLuint& id) const; - - void setRingTexture(GLuint id); - bool getRingTexture(GLuint& id) const; - - // Get Mass information - // - string getName() const; - double getMass() const; - double getSize() const; - void getPosition(double& x, double& y, double& z) const; - void getPreviousPosition(double& x, double& y, double& z) const; - void getDelta(double& dx, double& dy, double& dz) const; - void getColour(GLfloat& r, GLfloat& g, GLfloat& b) const; - - bool isMassless() const; - - // All resetting of various controls for collisions - // - void reset(double mass, double dx, double dy, double dz); - void reset(double mass); - - // Attract the object to the provided mass. Note that the supplied - // mass is left unaltered. - // - // Returns true if the two objects have collided - // - bool calcAttraction(Mass& m, double gr_const); - - // Move the mass along it's delta - // - void move(); - - void draw(bool solid, bool texture, DrawItem item) const; - - // Streaming - // - friend ostream& operator<<(ostream& os, const Mass& m); - - private: - string m_name; - double m_size; - double m_mass; - double m_scale; - double m_x,m_y,m_z; - double m_prevx,m_prevy,m_prevz; - double m_dx,m_dy,m_dz; - GLfloat m_r,m_g,m_b; - - bool m_massless; - - double m_rot; - double m_ang; - - int m_shield; - - bool m_textured; - GLuint m_texture_id; - - bool m_ring; - double m_ring_from,m_ring_to; - double m_ring_rot,m_ring_ang,m_ring_tilt; - GLfloat m_rr,m_rg,m_rb; - GLfloat m_ring_alpha; - bool m_ring_textured; - GLuint m_ring_id; - - double calcDistance2(Mass& m, double& dx, double& dy, double& dz); - void calcSize(); - }; +{ +public: + enum DrawItem {eMass, eRing}; + + Mass(); + Mass(const string& name, double mass, double scale, + double posx, double posy, double posz, + double dx, double dy, double dz, + GLfloat r, GLfloat g, GLfloat b, + double rot, int sheild=0); + virtual ~Mass(); + + // Define a ring + // + void setRing(double from, double to, + GLfloat r, GLfloat g, GLfloat b, GLfloat alpha, + double rot, double angle); + + // Set up an Open GL texture ID to use. It is assumed that + // texturing is not used till this member is called. + // + // The get function returns true if a texture has been assigned. + // + void setTexture(GLuint id); + bool getTexture(GLuint& id) const; + + void setRingTexture(GLuint id); + bool getRingTexture(GLuint& id) const; + + // Get Mass information + // + string getName() const; + double getMass() const; + double getSize() const; + void getPosition(double& x, double& y, double& z) const; + void getPreviousPosition(double& x, double& y, double& z) const; + void getDelta(double& dx, double& dy, double& dz) const; + void getColour(GLfloat& r, GLfloat& g, GLfloat& b) const; + + bool isMassless() const; + + // All resetting of various controls for collisions + // + void reset(double mass, double dx, double dy, double dz); + void reset(double mass); + + // Attract the object to the provided mass. Note that the supplied + // mass is left unaltered. + // + // Returns true if the two objects have collided + // + bool calcAttraction(Mass& m, double gr_const); + + // Move the mass along it's delta + // + void move(); + + void draw(bool solid, bool texture, DrawItem item) const; + + // Streaming + // + friend ostream& operator<<(ostream& os, const Mass& m); + +private: + string m_name; + double m_size; + double m_mass; + double m_scale; + double m_x,m_y,m_z; + double m_prevx,m_prevy,m_prevz; + double m_dx,m_dy,m_dz; + GLfloat m_r,m_g,m_b; + + bool m_massless; + + double m_rot; + double m_ang; + + int m_shield; + + bool m_textured; + GLuint m_texture_id; + + bool m_ring; + double m_ring_from,m_ring_to; + double m_ring_rot,m_ring_ang,m_ring_tilt; + GLfloat m_rr,m_rg,m_rb; + GLfloat m_ring_alpha; + bool m_ring_textured; + GLuint m_ring_id; + + double calcDistance2(Mass& m, double& dx, double& dy, double& dz); + void calcSize(); +}; // Routine to find masses from a vector of them @@ -30,51 +30,59 @@ #include "global.h" template <class Ty> class Matrix +{ +public: + Matrix() { - public: - Matrix() - { - int a,b; - - for(a=0;a<3;a++) - for(b=0;b<3;b++) - mat[a][b]=0; - } + int a,b; - ~Matrix() + for(a=0;a<3;a++) { + for(b=0;b<3;b++) + { + mat[a][b]=0; + } } + } - void identity() - { - int a,b; + ~Matrix() + { + } - for(a=0;a<3;a++) - for(b=0;b<3;b++) - mat[a][b]=(a==b) ? 1:0; - } + void identity() + { + int a,b; - void set(Ty x, Ty y, Ty z) + for(a=0;a<3;a++) { - identity(); - mat[0][0]=x; - mat[1][1]=y; - mat[2][2]=z; - mat[3][3]=1; + for(b=0;b<3;b++) + { + mat[a][b]=(a==b) ? 1:0; + } } + } - void get(Ty& x, Ty& y, Ty& z) - { - x=mat[0][0]; - y=mat[1][1]; - z=mat[2][2]; - } + void set(Ty x, Ty y, Ty z) + { + identity(); + mat[0][0] = x; + mat[1][1] = y; + mat[2][2] = z; + mat[3][3] = 1; + } + + void get(Ty& x, Ty& y, Ty& z) + { + x = mat[0][0]; + y = mat[1][1]; + z = mat[2][2]; + } - Matrix& operator*(Matrix<Ty>& m); + Matrix& operator*(Matrix<Ty>& m); - private: - Ty mat[4][4]; - }; +private: + Ty mat[4][4]; +}; #endif diff --git a/particles.cpp b/particles.cpp index 2603397..2bd9139 100644 --- a/particles.cpp +++ b/particles.cpp @@ -66,13 +66,13 @@ void Particles::draw() glBegin(GL_LINES); for(i=m_list.begin();i!=m_list.end();i++) - { + { i->a-=m_alpha_dec; glColor4f(i->r,i->g,i->b,i->a); glVertex3f(i->x1,i->y1,i->z1); glVertex3f(i->x2,i->y2,i->z2); - } + } glEnd(); } @@ -85,17 +85,19 @@ void Particles::update() // Delete dead particles // i=m_list.begin(); - + while ((i!=m_list.end())&&(i->a<=m_alpha_min)) - { + { m_list.pop_front(); i=m_list.begin(); - } + } // Update them // for(i=m_list.begin();i!=m_list.end();i++) + { i->a-=m_alpha_dec; + } } // END OF FILE // diff --git a/particles.h b/particles.h index 2619fb1..226dbf2 100644 --- a/particles.h +++ b/particles.h @@ -31,31 +31,31 @@ #include <list> class Particles +{ +public: + Particles(GLfloat alpha_dec, GLfloat alpha_min); + virtual ~Particles(); + + void add(GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat r, GLfloat g, GLfloat b); + + void draw(); + void update(); + +private: + struct Point { - public: - Particles(GLfloat alpha_dec, GLfloat alpha_min); - virtual ~Particles(); - - void add(GLfloat x1, GLfloat y1, GLfloat z1, - GLfloat x2, GLfloat y2, GLfloat z2, - GLfloat r, GLfloat g, GLfloat b); - - void draw(); - void update(); - - private: - struct Point - { - GLfloat r,g,b,a; - GLfloat x1,y1,z1; - GLfloat x2,y2,z2; - }; - - list<Point> m_list; - GLfloat m_alpha_dec; - GLfloat m_alpha_min; + GLfloat r,g,b,a; + GLfloat x1,y1,z1; + GLfloat x2,y2,z2; }; + list<Point> m_list; + GLfloat m_alpha_dec; + GLfloat m_alpha_min; +}; + #endif // END OF FILE // @@ -27,7 +27,7 @@ static const char id[]="$Id$"; #include "sparks.h" Sparks::Sparks(int num, GLfloat alpha_dec, GLfloat alpha_min, - int len, GLfloat delta) + int len, GLfloat delta) { m_num=max(num,1); m_alpha_dec=alpha_dec; @@ -53,7 +53,7 @@ void Sparks::add(GLfloat ox, GLfloat oy, GLfloat oz) p.life=m_life; for(f=0;f<m_num;f++) - { + { p.dx=DRand()*m_delta*2-m_delta; p.dy=DRand()*m_delta*2-m_delta; p.dz=DRand()*m_delta*2-m_delta; @@ -65,7 +65,7 @@ void Sparks::add(GLfloat ox, GLfloat oy, GLfloat oz) p.alpha=1.0f; m_list.push_back(p); - } + } } @@ -76,17 +76,17 @@ void Sparks::update() // Delete dead sparks // i=m_list.begin(); - + while ((i!=m_list.end())&&(i->alpha<=m_alpha_min)) - { + { m_list.pop_front(); i=m_list.begin(); - } + } // Update them // for(i=m_list.begin();i!=m_list.end();i++) - { + { i->x1+=i->dx; i->y1+=i->dy; i->z1+=i->dz; @@ -96,7 +96,7 @@ void Sparks::update() i->z2+=i->dz; i->alpha-=m_alpha_dec; - } + } } @@ -109,12 +109,12 @@ void Sparks::draw() glBegin(GL_LINES); for(i=m_list.begin();i!=m_list.end();i++) - { + { glColor4f(1.0,1.0,0.0,i->alpha); glVertex3f(i->x1,i->y1,i->z1); glColor4f(0.5,0.0,0.0,i->alpha); glVertex3f(i->x2,i->y2,i->z2); - } + } glEnd(); } @@ -31,37 +31,37 @@ #include <list> class Sparks - { - public: - Sparks(int num, GLfloat alpha_dec, GLfloat alpha_min, - int len, GLfloat delta); - virtual ~Sparks(); +{ +public: + Sparks(int num, GLfloat alpha_dec, GLfloat alpha_min, + int len, GLfloat delta); + virtual ~Sparks(); - void add(GLfloat ox, GLfloat oy, GLfloat oz); + void add(GLfloat ox, GLfloat oy, GLfloat oz); - void draw(); + void draw(); - void update(); + void update(); - private: - struct Point - { - GLfloat x1,y1,z1; - GLfloat x2,y2,z2; - GLfloat dx,dy,dz; - GLfloat alpha; - int life; - }; +private: + struct Point + { + GLfloat x1,y1,z1; + GLfloat x2,y2,z2; + GLfloat dx,dy,dz; + GLfloat alpha; + int life; + }; - list<Point> m_list; + list<Point> m_list; - int m_num; - GLfloat m_alpha_min; - GLfloat m_alpha_dec; - int m_life; - int m_len; - GLfloat m_delta; - }; + int m_num; + GLfloat m_alpha_min; + GLfloat m_alpha_dec; + int m_life; + int m_len; + GLfloat m_delta; +}; #endif diff --git a/test1.dat b/test1.dat new file mode 100644 index 0000000..d98a851 --- /dev/null +++ b/test1.dat @@ -0,0 +1,51 @@ +# For this test the two objects should fall into the centre with the same +# acceleration, independent of their mass. +# +camera 0.0, 0.0, -1000.0, 0.0; + +enable solid; +enable lighting; +disable texture; + +collide none; + +const 0.001; + +scale 10; + + +body centre, + 100, + 0,0,0, + 0,0,0, + 1,1,1, + 0; + +light centre,1,1,1; + + +plane xy; + +radial mass1, + 1, + centre, + 500, + 90, + 0, + 1,0,0, + 0; + +radial mass2, + 2, + centre, + 500, + 270, + 0, + 0,1,0, + 0; + +look centre; +look mass1; +look mass2; + +look_at centre; diff --git a/test2.dat b/test2.dat new file mode 100644 index 0000000..48b7c27 --- /dev/null +++ b/test2.dat @@ -0,0 +1,53 @@ +# For this test the two objects should orbit around the centre with the same +# acceleration, independent of their mass. +# +camera 0.0, 0.0, -1000.0, 0.0; + +enable solid; +enable lighting; +disable texture; + +collide none; + +const 0.001; + +scale 10; + + +body centre, + 100, + 0,0,0, + 0,0,0, + 1,1,1, + 0; + +light centre,1,1,1; + + +plane xy; + +radial mass1, + 1, + centre, + 300, + 90, + 1, + 1,0,0, + 0; + +radial mass2, + 2, + centre, + 300, + 270, + 1, + 0,1,0, + 0; + +look centre; +look mass1; +look mass2; + +look_at centre; + +particles 0.0001,0.0,1.0; |