From 19bbd5822593c7198dd54eb0f5d38fa1ed8d8fb7 Mon Sep 17 00:00:00 2001 From: Ian C Date: Wed, 18 Aug 2010 14:38:34 +0000 Subject: Reformatted code and altered the attraction rule to something a bit more correct. Also added two tests to prove it works. --- camera.h | 42 ++-- config.cpp | 647 +++++++++++++++++++++++++++++++--------------------------- config.h | 212 +++++++++---------- glgrav.cpp | 298 +++++++++++++++++---------- makefile | 6 +- mass.cpp | 142 +++++++++---- mass.h | 188 ++++++++--------- matrix.h | 74 ++++--- particles.cpp | 12 +- particles.h | 44 ++-- sparks.cpp | 20 +- sparks.h | 50 ++--- test1.dat | 51 +++++ test2.dat | 53 +++++ 14 files changed, 1073 insertions(+), 766 deletions(-) create mode 100644 test1.dat create mode 100644 test2.dat diff --git a/camera.h b/camera.h index d1c39c0..7bb42f9 100644 --- a/camera.h +++ b/camera.h @@ -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 diff --git a/config.cpp b/config.cpp index ebfd68b..5c74954 100644 --- a/config.cpp +++ b/config.cpp @@ -36,60 +36,66 @@ Config::Config() { int f; - m_error=""; + 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} - }; + } 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; @@ -128,37 +134,37 @@ bool Config::read(const string& fname,vector& mass) 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++; } + 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) 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++; } + 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) 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++; } + 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) toGLfloat(arg[10]), toDouble(arg[11])); if (mass.size()& mass) toDouble(arg[9])); if (mass.size()& mass) int f; for(f=0;f& mass) spd+=spd_i; if (mass.size()& 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& 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) 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& 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& 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& 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(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) found=false; for(sidx=0;sidx& 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& 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(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(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=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; diff --git a/config.h b/config.h index 46a3cfc..ea0fcc9 100644 --- a/config.h +++ b/config.h @@ -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); + // Note that the vector is added to. It must be cleared beforehand + // if required. + // + bool read(const string& file, vector& 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& l) const; + void look(vector& 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 m_look; - int m_look_at; - int m_travel_as; + vector 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& 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& 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 diff --git a/glgrav.cpp b/glgrav.cpp index 8e7e6a7..95b00b4 100644 --- a/glgrav.cpp +++ b/glgrav.cpp @@ -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::size_type f; for(f=0;f::size_type f; switch (item) - { + { case DBG_DUMPOBJ: for(f=0;f(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(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); @@ -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& mv, Mass& m,int no,double delta,int shield) texture=m.getTexture(id); for(f=0;f=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()=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; @@ -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;fmass.size() || !del_mass[f]) + { mass.push_back(new_mass[f]); + } + } for(f=0;fadd(static_cast(x), static_cast(y), static_cast(z), @@ -868,70 +927,95 @@ static void Update(void) 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); + } } diff --git a/makefile b/makefile index 297c53d..729eabe 100644 --- a/makefile +++ b/makefile @@ -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 diff --git a/mass.cpp b/mass.cpp index e83cf55..20f932c 100644 --- a/mass.cpp +++ b/mass.cpp @@ -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_xm.m_x) + { m_dx-=ga/(m_mass/dx); + } if (m_ym.m_y) + { m_dy-=ga/(m_mass/dy); + } if (m_zm.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& m, const string& name, Mass& ret) vector::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& m, const string& name, Mass& ret) bool findMass(vector& m, const string& name, vector::size_type& i) { for(i=0;i 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& m); + Matrix& operator*(Matrix& 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 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 m_list; - GLfloat m_alpha_dec; - GLfloat m_alpha_min; + GLfloat r,g,b,a; + GLfloat x1,y1,z1; + GLfloat x2,y2,z2; }; + list m_list; + GLfloat m_alpha_dec; + GLfloat m_alpha_min; +}; + #endif // END OF FILE // diff --git a/sparks.cpp b/sparks.cpp index 6a1484b..096e12a 100644 --- a/sparks.cpp +++ b/sparks.cpp @@ -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;falpha<=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(); } diff --git a/sparks.h b/sparks.h index 7c5deaf..63945b5 100644 --- a/sparks.h +++ b/sparks.h @@ -31,37 +31,37 @@ #include 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 m_list; + list 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; -- cgit v1.2.3