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 @@
+
+
+
+