// // glgrav - OpenGL N-Body gravity simulator // // Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.co.uk) // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // ------------------------------------------------------------------------- // // Mass // static const char id[]="$Id$"; #include "mass.h" // ---------------------------------------- CONSTRUCT/DESTRUCT/ASSIGN // Mass::Mass() { m_name=""; m_massless=false; m_mass=1.0; m_scale=1.0; calcSize(); m_x=0.0; m_y=0.0; m_z=0.0; m_r=1.0; m_g=1.0; m_b=1.0; m_shield=0; m_textured=false; m_texture_id=0; m_ring=false; m_ring_textured=false; m_ring_id=0; m_rr=0.0; m_rg=0.0; m_rb=0.0; m_ring_alpha=1.0; m_prevx=m_x; m_prevy=m_y; m_prevz=m_z; } 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) : m_delta(dx, dy, dz) { m_name=name; m_mass=mass; m_scale=scale; calcSize(); m_x=posx; m_y=posy; m_z=posz; m_r=r; m_g=g; m_b=b; m_rot=rot; m_ang=0; m_shield=shield; if (m_mass<=0.0) { m_mass=0.0001; m_massless=true; } else { m_massless=false; } m_ring=false; m_ring_textured=false; m_ring_id=0; m_rr=0.0; m_rg=0.0; m_rb=0.0; m_ring_alpha=1.0; m_prevx=m_x; m_prevy=m_y; m_prevz=m_z; } Mass::~Mass() { } // ---------------------------------------- PUBLIC MEMBERS // void Mass::setRing(double from, double to, GLfloat r, GLfloat g, GLfloat b, GLfloat alpha, double rot, double ang) { m_ring=true; m_ring_from=from; m_ring_to=to; m_rr=r; m_rg=g; m_rb=b; m_ring_alpha=alpha; m_ring_rot=rot; m_ring_tilt=ang; m_ring_ang=0.0; } void Mass::setTexture(GLuint id) { m_textured=true; m_texture_id=id; } bool Mass::getTexture(GLuint& id) const { id=m_texture_id; return m_textured; } void Mass::setRingTexture(GLuint id) { if (m_ring) { m_ring_textured=true; m_ring_id=id; } } bool Mass::getRingTexture(GLuint& id) const { id=m_ring_id; return m_ring_textured; } string Mass::getName() const { return m_name; } double Mass::getMass() const { return m_mass; } double Mass::getSize() const { return m_size; } bool Mass::isMassless() const { return m_massless; } void Mass::getPosition(double& x, double& y, double& z) const { x=m_x; y=m_y; z=m_z; } void Mass::getPreviousPosition(double& x, double& y, double& z) const { x=m_prevx; y=m_prevy; z=m_prevz; } void Mass::getDelta(double& dx, double& dy, double& dz) const { dx = m_delta.dx(); dy = m_delta.dy(); dz = m_delta.dz(); } void Mass::getColour(GLfloat& r, GLfloat& g, GLfloat& b) const { r=m_r; g=m_g; b=m_b; } void Mass::reset(double mass, double dx, double dy, double dz) { m_mass=mass; calcSize(); m_delta.Set(dx, dy, dz); if (m_mass<=0.0) { m_mass=0.0001; m_massless=true; } else { m_massless=false; } } void Mass::reset(double mass) { m_mass=mass; calcSize(); if (m_mass<=0.0) { m_mass=0.0001; m_massless=true; } else { m_massless=false; } } bool Mass::calcAttraction(Mass& m, double gr_const) { bool collide; double dist; double ga; double dx,dy,dz; if (m.m_massless) { return false; } dist=calcDistance2(m,dx,dy,dz); if (dist==0.0) { return !m_massless; } if (dist<(m_size + m.m_size) && (m_shield==0 || m.m_shield==0)) { collide=true; } else { collide=false; } ga = gr_const * (m.m_mass / (dist * dist)); Vec3D force(dx, dy, dz); force.SetLength(ga); m_delta.Add(force); return collide && !m_massless; } void Mass::move() { m_prevx=m_x; m_prevy=m_y; m_prevz=m_z; m_x+=m_delta.dx(); m_y+=m_delta.dy(); m_z+=m_delta.dz(); m_ang+=m_rot; m_ring_ang+=m_ring_rot; if (m_shield) { m_shield--; } } void Mass::draw(bool solid, bool texture, Mass::DrawItem item) const { const GLint sp=32; GLUquadric *q; if (m_massless && item==eMass) { GLboolean l=glIsEnabled(GL_LIGHTING); glDisable(GL_LIGHTING); glBegin(GL_POINTS); glColor4f(m_r,m_g,m_b,1.0f); glVertex3d(m_x,m_y,m_z); 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); glRotated(180.0,1.0,0.0,0.0); glRotated(180.0,0.0,0.0,1.0); gluDisk(q,m_size*m_ring_from,m_size*m_ring_to,sp,1); gluDeleteQuadric(q); } } } // ---------------------------------------- PRIVATE MEMBERS // double Mass::calcDistance2(Mass& m, double& dx, double& dy, double& dz) { dx = m.m_x-m_x; dy = m.m_y-m_y; dz = m.m_z-m_z; return sqrt((dx*dx)+(dy*dy)+(dz*dz)); } void Mass::calcSize() { m_size=m_mass*(3.0/4.0)*(1.0/M_PI); m_size=pow(m_size,0.333333333333333333333)*m_scale; if (m_size<1.0) { m_size=1.0; } } // ---------------------------------------- OTHER FUNCTIONS // 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_delta.dx() << ", " << m.m_delta.dy() << ", " << m.m_delta.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; } 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; } bool findMass(vector& m, const string& name, vector::size_type& i) { for(i=0;i