// // 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_dx=0.0; m_dy=0.0; m_dz=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_name=name; m_mass=mass; m_scale=scale; calcSize(); m_x=posx; m_y=posy; m_z=posz; m_dx=dx; m_dy=dy; m_dz=dz; 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_dx; dy=m_dy; dz=m_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_dx=dx; m_dy=dy; m_dz=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)*(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; } void Mass::move() { m_prevx=m_x; m_prevy=m_y; m_prevz=m_z; m_x+=m_dx; m_y+=m_dy; m_z+=m_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=abs(m_x-m.m_x); dy=abs(m_y-m.m_y); dz=abs(m_z-m.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_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; } 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