diff --git a/src/pulsaranimationwidget.cpp b/src/pulsaranimationwidget.cpp index c718c760da775ad1cbf15301c21db340f68c53da..a279743cb87e0330aaf00f6bf66e49503be6ce86 100644 --- a/src/pulsaranimationwidget.cpp +++ b/src/pulsaranimationwidget.cpp @@ -57,13 +57,16 @@ PulsarAnimationWidget::PulsarAnimationWidget(QWidget *parent) : m_quadricCompanion = NULL; m_quadricPulsarOrbitPlane = NULL; m_quadricPulsar = NULL; - m_quadricPulsarCone1 = NULL; - m_quadricPulsarCone2 = NULL; + m_quadricPulsarCone1Shell = NULL; + m_quadricPulsarCone2Shell = NULL; m_quadricPulsarSpinAxis = NULL; + m_quadricPulsarSpinAxisTop1 = NULL; + m_quadricPulsarSpinAxisTop2 = NULL; m_quadricPulsarMagneticAxis = NULL; // initialize texture pointers m_backgroundTexture = 0; + m_beamTexture = 0; // initial render timing settings m_framesPerSecond = 25; @@ -82,6 +85,11 @@ PulsarAnimationWidget::PulsarAnimationWidget(QWidget *parent) : m_companionSemiMajorAxis = (m_pulsarMass/m_companionMass) * m_pulsarSemiMajorAxis; // initial spin frequency of 0.5 Hz m_pulsarRotationDelta = (360.0 * 0.5) / m_framesPerSecond; + // beam properties (keep this order!) + m_pulsarBeamLength = 3.0f; + setPulsarBeamAngle(30); + + // update orbital period (based on settings above) updateOrbitPeriod(); @@ -109,12 +117,15 @@ PulsarAnimationWidget::~PulsarAnimationWidget() if(m_quadricCompanion) gluDeleteQuadric(m_quadricCompanion); if(m_quadricPulsarOrbitPlane) gluDeleteQuadric(m_quadricPulsarOrbitPlane); if(m_quadricPulsar) gluDeleteQuadric(m_quadricPulsar); - if(m_quadricPulsarCone1) gluDeleteQuadric(m_quadricPulsarCone1); - if(m_quadricPulsarCone2) gluDeleteQuadric(m_quadricPulsarCone2); + if(m_quadricPulsarCone1Shell) gluDeleteQuadric(m_quadricPulsarCone1Shell); + if(m_quadricPulsarCone2Shell) gluDeleteQuadric(m_quadricPulsarCone2Shell); if(m_quadricPulsarSpinAxis) gluDeleteQuadric(m_quadricPulsarSpinAxis); + if(m_quadricPulsarSpinAxisTop1) gluDeleteQuadric(m_quadricPulsarSpinAxisTop1); + if(m_quadricPulsarSpinAxisTop2) gluDeleteQuadric(m_quadricPulsarSpinAxisTop2); if(m_quadricPulsarMagneticAxis) gluDeleteQuadric(m_quadricPulsarMagneticAxis); if(m_backgroundTexture) deleteTexture(m_backgroundTexture); + if(m_beamTexture) deleteTexture(m_beamTexture); } void PulsarAnimationWidget::initializeGL() @@ -143,7 +154,6 @@ void PulsarAnimationWidget::initializeGL() glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glEnable(GL_LIGHT0); - glEnable(GL_LIGHTING); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); @@ -152,18 +162,22 @@ void PulsarAnimationWidget::initializeGL() m_quadricCompanion = gluNewQuadric(); m_quadricPulsarOrbitPlane = gluNewQuadric(); m_quadricPulsar = gluNewQuadric(); - m_quadricPulsarCone1 = gluNewQuadric(); - m_quadricPulsarCone2 = gluNewQuadric(); + m_quadricPulsarCone1Shell = gluNewQuadric(); + m_quadricPulsarCone2Shell = gluNewQuadric(); m_quadricPulsarSpinAxis = gluNewQuadric(); + m_quadricPulsarSpinAxisTop1 = gluNewQuadric(); + m_quadricPulsarSpinAxisTop2 = gluNewQuadric(); m_quadricPulsarMagneticAxis = gluNewQuadric(); gluQuadricNormals(m_quadricCompanionOrbitPlane, GLU_SMOOTH); gluQuadricNormals(m_quadricCompanion, GLU_SMOOTH); gluQuadricNormals(m_quadricPulsarOrbitPlane, GLU_SMOOTH); gluQuadricNormals(m_quadricPulsar, GLU_SMOOTH); - gluQuadricNormals(m_quadricPulsarCone1, GLU_SMOOTH); - gluQuadricNormals(m_quadricPulsarCone2, GLU_SMOOTH); + gluQuadricNormals(m_quadricPulsarCone1Shell, GLU_SMOOTH); + gluQuadricNormals(m_quadricPulsarCone2Shell, GLU_SMOOTH); gluQuadricNormals(m_quadricPulsarSpinAxis, GLU_SMOOTH); + gluQuadricNormals(m_quadricPulsarSpinAxisTop1, GLU_SMOOTH); + gluQuadricNormals(m_quadricPulsarSpinAxisTop2, GLU_SMOOTH); gluQuadricNormals(m_quadricPulsarMagneticAxis, GLU_SMOOTH); // query max texture size (estimate) @@ -193,16 +207,31 @@ void PulsarAnimationWidget::initializeGL() backgroundTexture = backgroundTexture.scaled(maxTextureSize, maxTextureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } + // prepare and check beam texture + QImage beamTexture(":/textures/resources/texture_beam.png"); + if(beamTexture.width() != beamTexture.height()) { + qWarning() << msgShape.arg(tr("Beam")); + } + else { + double integer = 0.0; + double fraction = 0.0; + fraction = modf(log(beamTexture.width()) / log(2.0), &integer); + if(fraction > 0.0) { + qWarning() << msgPower.arg(tr("Beam")); + } + } + if(beamTexture.width() > maxTextureSize) { + qWarning() << msgSize.arg(tr("beam").arg(maxTextureSize).arg(maxTextureSize)); + beamTexture = beamTexture.scaled(maxTextureSize, maxTextureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + } + // bind textures m_backgroundTexture = bindTexture(backgroundTexture, GL_TEXTURE_2D, GL_RGBA); + m_beamTexture = bindTexture(beamTexture, GL_TEXTURE_2D, GL_RGBA); // use mipmapped textures glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - - // enable 2D mapping (s/t coordinates, sphere map won't rotate texture!) - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); } void PulsarAnimationWidget::resizeGL(int w, int h) @@ -220,6 +249,8 @@ void PulsarAnimationWidget::resizeGL(int w, int h) void PulsarAnimationWidget::paintGL() { + GLfloat x,y,angle; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); @@ -272,10 +303,17 @@ void PulsarAnimationWidget::paintGL() glTranslatef(sin((m_orbitRotationAngle + 180.0) * deg2rad) * m_companionSemiMajorAxis, 0.0, cos((m_orbitRotationAngle + 180.0) * deg2rad) * m_companionSemiMajorAxis); + + // draw, with proper lighting + glEnable(GL_LIGHTING); gluSphere(m_quadricCompanion, 1.0, 32, 32); + glDisable(GL_LIGHTING); } glPopMatrix(); + // enable wireframe mode + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + // draw pulsar glPushMatrix(); { @@ -302,20 +340,15 @@ void PulsarAnimationWidget::paintGL() glPopMatrix(); } - // enable wireframe mode - glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); - // draw pulsar + // draw sphere, with proper lighting + glEnable(GL_LIGHTING); + glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); + glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); gluSphere(m_quadricPulsar, 1.0, 32, 32); - // disable wireframe mode - glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glDisable(GL_LIGHTING); } glPopMatrix(); - // TODO: should be located elsewhere - static GLfloat coneAmbient[] = {1.0, 1.0, 0.0, 1.0}; - static GLfloat coneDiffuse[] = {1.0, 1.0, 0.0, 1.0}; - static GLfloat coneSpecular[] = {1.0, 1.0, 0.5, 1.0}; - // first cone glPushMatrix(); { @@ -327,24 +360,72 @@ void PulsarAnimationWidget::paintGL() // draw magnetic axis (for both cones) if(m_showRotationAxes) { + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glColor3f(1.0f, 1.0f, 0.0f); glPushMatrix(); { - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, translucent); - glTranslatef(0.0, 0.0, -5.0); - gluCylinder(m_quadricPulsarMagneticAxis, 0.05, 0.05, 10.0, 32, 1); + glTranslatef(0.0, 0.0, -4.0); + gluCylinder(m_quadricPulsarMagneticAxis, 0.020, 0.020, 8.0, 32, 1); } glPopMatrix(); + glPushMatrix(); + { + glTranslatef(0.0, 0.0, -4.0); + gluDisk(m_quadricPulsarSpinAxisTop1, 0, 0.020, 32, 8); + } + glPopMatrix(); + glPushMatrix(); + { + glTranslatef(0.0, 0.0, 4.0); + gluDisk(m_quadricPulsarSpinAxisTop2, 0, 0.020, 32, 8); + } + glPopMatrix(); + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); } - glTranslatef(0.0, 0.0, -3.0); + glTranslatef(0.0, 0.0, -m_pulsarBeamLength); + + // draw first cone's outer layer + glBegin(GL_TRIANGLE_FAN); + { + // Pinnacle of cone is shared vertex for fan, moved up z-axis + // to produce a cone instead of a circle + glColor4f(1.0f, 1.0f, 0.0f, 0.33f); + glVertex3f(0.0f, 0.0f, m_pulsarBeamLength); + + // Loop around in a circle and specify even points along the circle + // as the vertices of the triangle fan (32 sections) + for(angle = 0.0f; angle < (2.0f*PI); angle += (PI/32.0f)) + { + // Calculate x and y position of the next vertex + x = m_pulsarBeamOuterRadius * sin(angle); + y = m_pulsarBeamOuterRadius * cos(angle); + + // Specify the next vertex for the triangle fan + glVertex2f(x, y); + } + } + glEnd(); + + // draw first cone's "base" (textured bottom to visualize beam intensity) + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + // create texture coordinates and enable texturing + gluQuadricTexture(m_quadricPulsarCone1Shell, GL_TRUE); + glBindTexture(GL_TEXTURE_2D, m_beamTexture); + glEnable(GL_TEXTURE_2D); + + gluDisk(m_quadricPulsarCone1Shell, 0, m_pulsarBeamOuterRadius, 32, 1); + + // disable texturing + glDisable(GL_TEXTURE_2D); - glMaterialfv(GL_FRONT, GL_AMBIENT, coneAmbient); - glMaterialfv(GL_FRONT, GL_DIFFUSE, coneDiffuse); - gluCylinder(m_quadricPulsarCone1, 0.475, 0.0, 3.0, 32, 32); + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); } glPopMatrix(); - // second cone + // second cone (pointing towards from camera) glPushMatrix(); { glRotatef(-90.0, 1.0, 0.0, 0.0); @@ -353,43 +434,55 @@ void PulsarAnimationWidget::paintGL() glRotatef(m_pulsarRotationAngle - 90.0, 0.0, 0.0, 1.0); glRotatef(m_pulsarMagneticAxisInclination, 1.0, 0.0, 0.0); - glTranslatef(0.0, 0.0, -3.0); + glTranslatef(0.0, 0.0, -m_pulsarBeamLength); - glMaterialfv(GL_FRONT, GL_AMBIENT, coneAmbient); - glMaterialfv(GL_FRONT, GL_DIFFUSE, coneDiffuse); - gluCylinder(m_quadricPulsarCone2, 0.475, 0.0, 3.0, 32, 32); - } - glPopMatrix(); - } - glPopMatrix(); + // draw second cone's outer layer + glBegin(GL_TRIANGLE_FAN); + { + // Pinnacle of cone is shared vertex for fan, moved up z-axis + // to produce a cone instead of a circle + glColor4f(1.0f, 1.0f, 0.0f, 0.33f); + glVertex3f(0.0f, 0.0f, m_pulsarBeamLength); + + // Loop around in a circle and specify even points along the circle + // as the vertices of the triangle fan (32 sections) + for(angle = 0.0f; angle < (2.0f*PI); angle += (PI/32.0f)) + { + // Calculate x and y position of the next vertex + x = m_pulsarBeamOuterRadius * sin(angle); + y = m_pulsarBeamOuterRadius * cos(angle); - // save current state (the following is using parallel projection) - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - { - glLoadIdentity(); - glOrtho(0, width(), 0, height(), 0.1, 501.0); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - { - glLoadIdentity(); + // Specify the next vertex for the triangle fan + glVertex2f(x, y); + } + } + glEnd(); - // draw backdrop (independent parallel projection) - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_specular); - glTranslatef(0.0, 0.0, -501.0); - drawTexture(QPointF(0.0, 0.0), m_backgroundTexture); + // draw second cone's "base" (textured bottom to visualize beam intensity) + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - // restore original state - glMatrixMode(GL_PROJECTION); + // create texture coordinates and enable texturing + gluQuadricTexture(m_quadricPulsarCone2Shell, GL_TRUE); + glBindTexture(GL_TEXTURE_2D, m_beamTexture); + glEnable(GL_TEXTURE_2D); + + gluDisk(m_quadricPulsarCone2Shell, 0, m_pulsarBeamOuterRadius, 32, 1); + + // disable texturing + glDisable(GL_TEXTURE_2D); } glPopMatrix(); - glMatrixMode(GL_MODELVIEW); } glPopMatrix(); + // back to solid rendering + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + // draw orbital planes if(m_cameraInteraction || m_showOrbits) { glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, translucent); + glEnable(GL_LIGHTING); static double sizeOffset = 0.25; @@ -424,6 +517,8 @@ void PulsarAnimationWidget::paintGL() 64, 1); } glPopMatrix(); + + glDisable(GL_LIGHTING); } // save current state (the following is using parallel projection) @@ -629,6 +724,23 @@ void PulsarAnimationWidget::setPulsarMagneticAxisInclination(const int degrees) updateGL(); } +void PulsarAnimationWidget::setPulsarBeamAngle(const int degrees) +{ + double beamTexturePeakCorrectionFactor = 0.83; + double correctedOuterRadius; + + // compute visual radius + m_pulsarBeamOuterRadius = tan(deg2rad * degrees * 0.5f) * m_pulsarBeamLength; + + // compute corrected angle for pulse profile + correctedOuterRadius = m_pulsarBeamOuterRadius * beamTexturePeakCorrectionFactor; + m_pulsarBeamAngle = 2 * atan(correctedOuterRadius / m_pulsarBeamLength) * 180.0/PI; + + updatePulseProfile(); + + updateGL(); +} + void PulsarAnimationWidget::updateOrbitPeriod() { m_orbitalPeriod = 3.1553e7 * sqrt( diff --git a/src/pulsaranimationwidget.h b/src/pulsaranimationwidget.h index c0a71cf0640050043cb6a337a56b9a7d51326afb..7dc21bd829876e50fd0467324976320bed44e1c2 100644 --- a/src/pulsaranimationwidget.h +++ b/src/pulsaranimationwidget.h @@ -46,6 +46,7 @@ public: void setPulsarSpinAxisInclination(const int degrees); void setPulsarMagneticAxisInclination(const int degrees); void setPulsarSemiMajorAxis(const double length); + void setPulsarBeamAngle(const int degrees); public slots: void runAnimation(); @@ -84,12 +85,15 @@ private: GLUquadricObj *m_quadricCompanion; GLUquadricObj *m_quadricPulsarOrbitPlane; GLUquadricObj *m_quadricPulsar; - GLUquadricObj *m_quadricPulsarCone1; - GLUquadricObj *m_quadricPulsarCone2; + GLUquadricObj *m_quadricPulsarCone1Shell; + GLUquadricObj *m_quadricPulsarCone2Shell; GLUquadricObj *m_quadricPulsarSpinAxis; + GLUquadricObj *m_quadricPulsarSpinAxisTop1; + GLUquadricObj *m_quadricPulsarSpinAxisTop2; GLUquadricObj *m_quadricPulsarMagneticAxis; GLuint m_backgroundTexture; + GLuint m_beamTexture; int m_framesPerSecond; @@ -107,6 +111,9 @@ private: double m_pulsarSpinAxisInclination; double m_pulsarMagneticAxisInclination; + double m_pulsarBeamLength; + double m_pulsarBeamAngle; + double m_pulsarBeamOuterRadius; bool m_showOrbits; bool m_showRotationAxes; diff --git a/src/pulsatingscience.qrc b/src/pulsatingscience.qrc index 9cf723b1effd0d73df9372fb08b88c27211f8f8f..cdaff055496e0da4586a2610104f6a43d3ebe40a 100644 --- a/src/pulsatingscience.qrc +++ b/src/pulsatingscience.qrc @@ -14,5 +14,6 @@ resources/texture_background_carina.png + resources/texture_beam.png diff --git a/src/resources/texture_beam.png b/src/resources/texture_beam.png new file mode 100644 index 0000000000000000000000000000000000000000..eda270f8d0d38fa55608e9572fa6e78662992ddc Binary files /dev/null and b/src/resources/texture_beam.png differ diff --git a/src/resources/texture_beam.svg b/src/resources/texture_beam.svg new file mode 100644 index 0000000000000000000000000000000000000000..3b0d62a200412dec16e5140efccfb84568e128ad --- /dev/null +++ b/src/resources/texture_beam.svg @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + +