pulsaranimationwidget.cpp 17.1 KB
Newer Older
Oliver Bock's avatar
Oliver Bock committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/******************************************************************************
 *   Copyright (C) 2008 by Oliver Bock                                        *
 *   oliver.bock[AT]aei.mpg.de                                                *
 *                                                                            *
 *   This file is part of PulsatingScience.                                   *
 *                                                                            *
 *   PulsatingScience 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, version 3 of the License.               *
 *                                                                            *
 *   PulsatingScience 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 PulsatingScience. If not, see <http://www.gnu.org/licenses/>. *
 *                                                                            *
 ******************************************************************************/

#include "pulsaranimationwidget.h"

23
24
const float PulsarAnimationWidget::deg2rad = PI/180.0f;

Oliver Bock's avatar
Oliver Bock committed
25
PulsarAnimationWidget::PulsarAnimationWidget(QWidget *parent) :
Oliver Bock's avatar
Oliver Bock committed
26
	QGLWidget(QGLFormat(QGL::AlphaChannel | QGL::SampleBuffers), parent),
27
28
	m_frameTimer(),
	m_pulseProfile(360, 0.0f)
Oliver Bock's avatar
Oliver Bock committed
29
{
Oliver Bock's avatar
Oliver Bock committed
30
31
32
33
34
35
	if(!format().directRendering()) {
		qWarning("Sorry, no direct rendering support for animation...");
	}
	if(!format().doubleBuffer()) {
		qWarning("Sorry, no double buffering support for animation...");
	}
36
	if(!format().rgba()) {
Oliver Bock's avatar
Oliver Bock committed
37
		qWarning("Sorry, no RGBA support for animation...");
38
39
	}
	if(!format().alpha()) {
Oliver Bock's avatar
Oliver Bock committed
40
		qWarning("Sorry, no alpha channel support for animation...");
41
	}
Oliver Bock's avatar
Oliver Bock committed
42
	if(!format().sampleBuffers()) {
Oliver Bock's avatar
Oliver Bock committed
43
		qWarning("Sorry, no multisampling support for animation...");
Oliver Bock's avatar
Oliver Bock committed
44
	}
45

Oliver Bock's avatar
Oliver Bock committed
46
    connect(&m_frameTimer, SIGNAL(timeout()), this, SLOT(updateFrame()));
Oliver Bock's avatar
Oliver Bock committed
47

Oliver Bock's avatar
Oliver Bock committed
48
49
    m_quadricCompanionOrbitPlane = NULL;
    m_quadricCompanion = NULL;
50
    m_quadricPulsarOrbitPlane = NULL;
Oliver Bock's avatar
Oliver Bock committed
51
    m_quadricPulsar = NULL;
52
53
	m_quadricPulsarCone1 = NULL;
	m_quadricPulsarCone2 = NULL;
54
	m_quadricPulsarSpinAxis = NULL;
55
	m_quadricPulsarMagneticAxis = NULL;
Oliver Bock's avatar
Oliver Bock committed
56

57
58
	m_pulsarTexture = 0;
	m_backgroundTexture = 0;
59

Oliver Bock's avatar
Oliver Bock committed
60
	m_framesPerSecond = 25;
61

62
	resetParameters();
63

Oliver Bock's avatar
Oliver Bock committed
64
65
66
	m_pulsarMass = 1.4f;
	m_companionMass = 1.4f;

Oliver Bock's avatar
Oliver Bock committed
67
	m_showRotationAxes = false;
68
	m_cameraInteraction = false;
69
70
	m_mouseLastX = 0;
	m_mouseLastY = 0;
Oliver Bock's avatar
Oliver Bock committed
71
	m_mouseAngleH = 90.0f;
72
	m_mouseAngleV = 30.0f;
73
	m_cameraZoom = 15.0f;
74
75
76
	m_cameraZoomLBound = 2.0f;

	updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
77
78

	updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
79
80
81
82
}

PulsarAnimationWidget::~PulsarAnimationWidget()
{
Oliver Bock's avatar
Oliver Bock committed
83
84
	if(m_quadricCompanionOrbitPlane) gluDeleteQuadric(m_quadricCompanionOrbitPlane);
	if(m_quadricCompanion) gluDeleteQuadric(m_quadricCompanion);
85
	if(m_quadricPulsarOrbitPlane) gluDeleteQuadric(m_quadricPulsarOrbitPlane);
Oliver Bock's avatar
Oliver Bock committed
86
87
88
	if(m_quadricPulsar) gluDeleteQuadric(m_quadricPulsar);
	if(m_quadricPulsarCone1) gluDeleteQuadric(m_quadricPulsarCone1);
	if(m_quadricPulsarCone2) gluDeleteQuadric(m_quadricPulsarCone2);
89
	if(m_quadricPulsarSpinAxis) gluDeleteQuadric(m_quadricPulsarSpinAxis);
90
	if(m_quadricPulsarMagneticAxis) gluDeleteQuadric(m_quadricPulsarMagneticAxis);
91
92
93

	if(m_pulsarTexture) deleteTexture(m_pulsarTexture);
	if(m_backgroundTexture) deleteTexture(m_backgroundTexture);
Oliver Bock's avatar
Oliver Bock committed
94
95
96
97
}

void PulsarAnimationWidget::initializeGL()
{
Oliver Bock's avatar
Oliver Bock committed
98
99
100
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClearDepth(1.0f);
	glDepthFunc(GL_LEQUAL);
101
102
103
	glEnable(GL_DEPTH_TEST);

	glShadeModel(GL_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
104
105
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

106
	GLfloat LightAmbient[] = { 0.3f, 0.3f, 0.3f, 1.0f };
Oliver Bock's avatar
Oliver Bock committed
107
108
109
110
111
112
113
114
115
	GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat LightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat LightPosition[] = { 0.0f, 0.0f, 3.0f, 1.0f };
	GLfloat spot_direction[] = { 0.0, 0.0, -1.0 };

	glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpecular);
	glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
116
	glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 50.0);
Oliver Bock's avatar
Oliver Bock committed
117
	glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
118
	glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 10.0);
Oliver Bock's avatar
Oliver Bock committed
119
120
121
122

	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHTING);
Oliver Bock's avatar
Oliver Bock committed
123

124
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
125
	glEnable(GL_BLEND);
126

Oliver Bock's avatar
Oliver Bock committed
127
128
	m_quadricCompanionOrbitPlane = gluNewQuadric();
	m_quadricCompanion = gluNewQuadric();
129
	m_quadricPulsarOrbitPlane = gluNewQuadric();
Oliver Bock's avatar
Oliver Bock committed
130
131
132
	m_quadricPulsar = gluNewQuadric();
    m_quadricPulsarCone1 = gluNewQuadric();
    m_quadricPulsarCone2 = gluNewQuadric();
133
    m_quadricPulsarSpinAxis = gluNewQuadric();
134
    m_quadricPulsarMagneticAxis = gluNewQuadric();
135

Oliver Bock's avatar
Oliver Bock committed
136
137
    gluQuadricNormals(m_quadricCompanionOrbitPlane, GLU_SMOOTH);
    gluQuadricNormals(m_quadricCompanion, GLU_SMOOTH);
138
    gluQuadricNormals(m_quadricPulsarOrbitPlane, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
139
140
141
    gluQuadricNormals(m_quadricPulsar, GLU_SMOOTH);
    gluQuadricNormals(m_quadricPulsarCone1, GLU_SMOOTH);
    gluQuadricNormals(m_quadricPulsarCone2, GLU_SMOOTH);
142
    gluQuadricNormals(m_quadricPulsarSpinAxis, GLU_SMOOTH);
143
    gluQuadricNormals(m_quadricPulsarMagneticAxis, GLU_SMOOTH);
144

145
    // load textures
146
    m_pulsarTexture = bindTexture(QImage(":/textures/resources/texture_pulsar.png"), GL_TEXTURE_2D, GL_RGBA);
147
    m_backgroundTexture = bindTexture(QImage(":/textures/resources/texture_background.png"), GL_TEXTURE_2D, GL_RGBA);
148

149
    // use mipmapped textures
150
151
152
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

Oliver Bock's avatar
Oliver Bock committed
153
154
155
    // 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);
Oliver Bock's avatar
Oliver Bock committed
156
157
158
159
}

void PulsarAnimationWidget::resizeGL(int w, int h)
{
Oliver Bock's avatar
Oliver Bock committed
160
161
162
163
164
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

Oliver Bock's avatar
Oliver Bock committed
165
	gluPerspective(45.0f, (GLfloat)w / (GLfloat)h, 0.1f, 500.0f);
Oliver Bock's avatar
Oliver Bock committed
166
167
168
169
170
171
172
173
174
175
176
177

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void PulsarAnimationWidget::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

178
179
	gluLookAt(m_cameraPosX, m_cameraPosY, m_cameraPosZ,
			  0.0, 0.0, 0.0,
180
			  0.0, 1.0, 0.0);
Oliver Bock's avatar
Oliver Bock committed
181
182
183
184
185

	// TODO: should be located elsewhere
	static GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
	static GLfloat mat_diffuse[] = { 0.5, 0.5, 0.5, 1.0 };
	static GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
186
	static GLfloat low_shininess[] = { 2.5 };
187
	static GLfloat translucent[] = { 1.0, 1.0, 1.0, 0.33 };
188

Oliver Bock's avatar
Oliver Bock committed
189
190
191
192
193
	glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
	glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);
	glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
Oliver Bock's avatar
Oliver Bock committed
194

195
	// draw companion
Oliver Bock's avatar
Oliver Bock committed
196
	glPushMatrix();
Oliver Bock's avatar
Oliver Bock committed
197
		glTranslatef(sin((m_orbitRotationAngle + 180) * deg2rad) * m_companionSemiMajorAxis,
198
					 0.0f,
Oliver Bock's avatar
Oliver Bock committed
199
200
					 cos((m_orbitRotationAngle + 180) * deg2rad) * m_companionSemiMajorAxis);
		gluSphere(m_quadricCompanion, 1.0f, 32, 32);
Oliver Bock's avatar
Oliver Bock committed
201
202
	glPopMatrix();

203
	// draw pulsar
Oliver Bock's avatar
Oliver Bock committed
204
	glPushMatrix();
Oliver Bock's avatar
Oliver Bock committed
205
		glTranslatef(sin(m_orbitRotationAngle * deg2rad) * m_pulsarSemiMajorAxis,
206
					 0.0f,
Oliver Bock's avatar
Oliver Bock committed
207
					 cos(m_orbitRotationAngle * deg2rad) * m_pulsarSemiMajorAxis);
208
209

		glPushMatrix();
210
211
			glRotatef(m_pulsarSpinAxisInclination, 0.0f, 0.0f, 1.0f);
			glRotatef(m_pulsarRotationAngle, 0.0f, 1.0f, 0.0f);
212

213
			// draw spin axis
Oliver Bock's avatar
Oliver Bock committed
214
			if(m_showRotationAxes) {
215
216
				glPushMatrix();
					glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, translucent);
217
					glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
218
219
220
221
222
					glTranslatef(0.0f, 0.0f, -5.0f);
					gluCylinder(m_quadricPulsarSpinAxis, 0.05f, 0.05f, 10.0f, 32, 1);
				glPopMatrix();
			}

223
224
225
226
227
			// create texture coordinates and enable texturing
	        glEnable(GL_TEXTURE_GEN_S);
	        glEnable(GL_TEXTURE_GEN_T);
	        glBindTexture(GL_TEXTURE_2D, m_pulsarTexture);
	        glEnable(GL_TEXTURE_2D);
228
229
230

			glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
231
			gluSphere(m_quadricPulsar, 1.0f, 32, 32);
232

233
			// disable texturing
234
235
236
	        glDisable(GL_TEXTURE_GEN_S);
	        glDisable(GL_TEXTURE_GEN_T);
	        glDisable(GL_TEXTURE_2D);
237
238
		glPopMatrix();

239
240
241
242
243
244
245
		// 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 };

		glMaterialfv(GL_FRONT, GL_SPECULAR, coneSpecular);

246
		// first cone
247
		glPushMatrix();
248
249
250
251
252
			glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
			glRotatef(m_pulsarSpinAxisInclination, 0.0f, 1.0f, 0.0f);

			glRotatef(-m_pulsarRotationAngle - 90.0f, 0.0f, 0.0f, 1.0f);
			glRotatef(-m_pulsarMagneticAxisInclination, 1.0f, 0.0f, 0.0f);
253

254
			// draw magnetic axis (for both cones)
Oliver Bock's avatar
Oliver Bock committed
255
			if(m_showRotationAxes) {
256
257
258
259
260
				glPushMatrix();
					glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, translucent);
					glTranslatef(0.0f, 0.0f, -5.0f);
					gluCylinder(m_quadricPulsarMagneticAxis, 0.05f, 0.05f, 10.0f, 32, 1);
				glPopMatrix();
261
262
			}

263
			glTranslatef(0.0f, 0.0f, -4.0f);
264
265
266

			glMaterialfv(GL_FRONT, GL_AMBIENT, coneAmbient);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, coneDiffuse);
267
			gluCylinder(m_quadricPulsarCone1, 0.475f, 0.0f, 3.0f, 32, 32);
268
269
		glPopMatrix();

270
		// second cone
271
		glPushMatrix();
272
273
			glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
			glRotatef(-m_pulsarSpinAxisInclination, 0.0f, 1.0f, 0.0f);
274

275
276
			glRotatef(m_pulsarRotationAngle - 90.0f, 0.0f, 0.0f, 1.0f);
			glRotatef(m_pulsarMagneticAxisInclination, 1.0f, 0.0f, 0.0f);
277

278
			glTranslatef(0.0f, 0.0f, -4.0f);
279
280
281

			glMaterialfv(GL_FRONT, GL_AMBIENT, coneAmbient);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, coneDiffuse);
282
			gluCylinder(m_quadricPulsarCone2, 0.475f, 0.0f, 3.0f, 32, 32);
283
		glPopMatrix();
Oliver Bock's avatar
Oliver Bock committed
284
	glPopMatrix();
285

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
	// save current state
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0, width(), 0, height(), 0.1f, 501.0f);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	// draw backdrop (independent parallel projection)
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_specular);
	glTranslatef(0.0f, 0.0f, -501.0f);
	drawTexture(QPointF(0.0f, 0.0f), m_backgroundTexture);

	// restore original state
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

Oliver Bock's avatar
Oliver Bock committed
306
	// draw orbital planes
307
	if(m_cameraInteraction) {
308
		glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, translucent);
309

310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
		static float sizeOffset = 0.25f;

		// companion's plane (only if not identical with pulsar's)
		if(m_companionSemiMajorAxis != m_pulsarSemiMajorAxis) {
			glPushMatrix();
				glRotatef(90.0f, 1.0f, 0.0f, 0.0f);

				// separate them slightly in case of overlap
				// based on ugly mass diff check (no collision detection)
				// single known problematic pair: (m_c=1.4, m_p=1.5)
				if((int)(10*(m_pulsarMass-m_companionMass)+0.5f) == 1){
					glTranslatef(0.0f, 0.0f, 0.01f);
				}

				gluDisk(m_quadricCompanionOrbitPlane,
						m_companionSemiMajorAxis - sizeOffset,
						m_companionSemiMajorAxis + sizeOffset,
						64, 1);
			glPopMatrix();
		}

		// pulsar's plane
Oliver Bock's avatar
Oliver Bock committed
332
333
		glPushMatrix();
			glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
334
			gluDisk(m_quadricPulsarOrbitPlane,
335
336
					m_pulsarSemiMajorAxis - sizeOffset,
					m_pulsarSemiMajorAxis + sizeOffset,
337
338
					64, 1);
		glPopMatrix();
339
	}
Oliver Bock's avatar
Oliver Bock committed
340
341
}

Oliver Bock's avatar
Oliver Bock committed
342
343
void PulsarAnimationWidget::runAnimation()
{
Oliver Bock's avatar
Oliver Bock committed
344
	m_frameTimer.start(1000.0f / m_framesPerSecond);
Oliver Bock's avatar
Oliver Bock committed
345
}
Oliver Bock's avatar
Oliver Bock committed
346

Oliver Bock's avatar
Oliver Bock committed
347
348
349
350
351
352
353
354
void PulsarAnimationWidget::pauseAnimation()
{
	m_frameTimer.stop();
}

void PulsarAnimationWidget::stopAnimation()
{
	m_frameTimer.stop();
355
	resetParameters();
Oliver Bock's avatar
Oliver Bock committed
356
357
358
359

	updateGL();
}

Oliver Bock's avatar
Oliver Bock committed
360
void PulsarAnimationWidget::updateFrame()
Oliver Bock's avatar
Oliver Bock committed
361
{
Oliver Bock's avatar
Oliver Bock committed
362
363
364
	m_pulsarRotationAngle += m_pulsarRotationDelta;
	if(m_pulsarRotationAngle > 360) {
		m_pulsarRotationAngle = 0.0f;
365
		updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
366
	}
Oliver Bock's avatar
Oliver Bock committed
367
368
369
	m_orbitRotationAngle += m_orbitRotationDelta;
	if(m_orbitRotationAngle > 360) {
		m_orbitRotationAngle = 0.0f;
Oliver Bock's avatar
Oliver Bock committed
370
371
	}

Oliver Bock's avatar
Oliver Bock committed
372
	updateGL();
Oliver Bock's avatar
Oliver Bock committed
373
374

	emit pulsarAnimationStep(m_pulsarRotationDelta);
375
376
}

Oliver Bock's avatar
Oliver Bock committed
377
378
379
380
381
382
383
void PulsarAnimationWidget::showRotationAxes(bool enabled)
{
	m_showRotationAxes = enabled;

	updateGL();
}

384
385
void PulsarAnimationWidget::mousePressEvent(QMouseEvent *event)
{
386
387
	Q_UNUSED(event);

388
389
390
391
	m_cameraInteraction = true;
	updateGL();
}

392
393
394
395
396
397
void PulsarAnimationWidget::mouseMoveEvent(QMouseEvent *event)
{
	Qt::MouseButtons buttons = event->buttons();
	if((buttons & Qt::LeftButton) == Qt::LeftButton) {
		if(m_mouseLastX != 0) {
			m_mouseAngleH -= (m_mouseLastX - event->x()) / 2;
Oliver Bock's avatar
Oliver Bock committed
398
			m_mouseAngleH = m_mouseAngleH < 360 ? m_mouseAngleH : 0;
399
400
401
402

		}
		if(m_mouseLastY != 0) {
			m_mouseAngleV -= (m_mouseLastY - event->y()) / 2;
Oliver Bock's avatar
Oliver Bock committed
403
404
			m_mouseAngleV = m_mouseAngleV < 90 ? m_mouseAngleV : 90;
			m_mouseAngleV = m_mouseAngleV > -90 ? m_mouseAngleV : -90;
405
406
407
408
409
410
411
412
		}

		m_mouseLastX = event->x();
		m_mouseLastY = event->y();
	}
	else if((buttons & Qt::RightButton) == Qt::RightButton) {
		if(m_mouseLastY != 0) {
			m_cameraZoom -= (m_mouseLastY - event->y()) / 2;
Oliver Bock's avatar
Oliver Bock committed
413
			m_cameraZoom = m_cameraZoom >= m_cameraZoomLBound ? m_cameraZoom : m_cameraZoomLBound;
414
415
416
417
418
419
420
421
422
423
424
			updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
		}

		m_mouseLastY = event->y();
	}

	updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
}

void PulsarAnimationWidget::mouseReleaseEvent(QMouseEvent *event)
{
425
426
	Q_UNUSED(event);

427
428
	m_mouseLastX = 0;
	m_mouseLastY = 0;
429
430
	m_cameraInteraction = false;
	updateGL();
431
432
433
434
435
436
}

void PulsarAnimationWidget::updateCameraPosition(const int angleH, const int angleV, const float zoom)
{
	m_cameraPosX = sin(angleH * deg2rad) * zoom;
	m_cameraPosY = sin(angleV * deg2rad) * zoom;
Oliver Bock's avatar
Oliver Bock committed
437
	m_cameraPosZ = cos(angleH * deg2rad) * cos(fabs(angleV * deg2rad)) * zoom;
438

439
440
	updatePulseProfile();

441
442
443
	updateGL();
}

Oliver Bock's avatar
Oliver Bock committed
444
445
446
447
448
void PulsarAnimationWidget::setFramePerSecond(const unsigned int fps)
{
	m_framesPerSecond = fps;
}

Oliver Bock's avatar
Oliver Bock committed
449
void PulsarAnimationWidget::setPulsarSemiMajorAxis(const float length)
Oliver Bock's avatar
Oliver Bock committed
450
{
Oliver Bock's avatar
Oliver Bock committed
451
452
453
	m_pulsarSemiMajorAxis = length;
	m_companionSemiMajorAxis = (m_pulsarMass/m_companionMass) * m_pulsarSemiMajorAxis;
	updateOrbitPeriod();
454
	updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
455
456

	updateGL();
Oliver Bock's avatar
Oliver Bock committed
457
}
458

Oliver Bock's avatar
Oliver Bock committed
459
void PulsarAnimationWidget::setCompanionMass(const float mass)
460
{
Oliver Bock's avatar
Oliver Bock committed
461
462
	m_companionMass = mass;
	updateOrbitRadii();
463
	updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
464
465

	updateGL();
466
467
}

Oliver Bock's avatar
Oliver Bock committed
468
void PulsarAnimationWidget::setPulsarMass(const float mass)
469
{
Oliver Bock's avatar
Oliver Bock committed
470
471
	m_pulsarMass = mass;
	updateOrbitRadii();
472
	updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
473
474
475
476
477
478
479

	updateGL();
}

void PulsarAnimationWidget::setPulsarSpinFrequency(const float frequency)
{
	m_pulsarRotationDelta = (360.0f * frequency) / m_framesPerSecond;
480
	updatePulseProfile();
481
}
482

483
484
485
void PulsarAnimationWidget::setPulsarSpinAxisInclination(const int degrees)
{
	m_pulsarSpinAxisInclination = degrees;
486
	updatePulseProfile();
487
488
489
490

	updateGL();
}

491
492
493
494
495
496
void PulsarAnimationWidget::setPulsarMagneticAxisInclination(const int degrees)
{
	m_pulsarMagneticAxisInclination = degrees;

	updateGL();
}
497

Oliver Bock's avatar
Oliver Bock committed
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
void PulsarAnimationWidget::updateOrbitPeriod()
{
	m_orbitalPeriod = 3.1553e7 * sqrt(
						(pow(m_pulsarSemiMajorAxis,3) * pow(m_pulsarMass+m_companionMass,2)) /
						 pow(m_companionMass,3)
					  );

	// visual correction factor (increase orbital momentum)
	double visualCorrection = 1e-8;

	m_orbitRotationDelta  = (360.0 / (m_orbitalPeriod*visualCorrection)) / m_framesPerSecond;
}

void PulsarAnimationWidget::updateOrbitRadii()
{
	m_pulsarSemiMajorAxis = 1.0015e-5 * pow(
								(pow(m_orbitalPeriod,2) * pow(m_companionMass,3)) /
								 pow(m_pulsarMass+m_companionMass,2),
								 1.0/3.0
							);

	m_companionSemiMajorAxis = (m_pulsarMass/m_companionMass) * m_pulsarSemiMajorAxis;

	emit pulsarSemiMajorAxisUpdated(m_pulsarSemiMajorAxis);
}

524
525
526
527
void PulsarAnimationWidget::resetParameters()
{
	m_pulsarRotationAngle = 0.0f;
	m_orbitRotationAngle = 0.0f;
Oliver Bock's avatar
Oliver Bock committed
528
529

	emit pulsarAnimationReset();
530
}
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

void PulsarAnimationWidget::updatePulseProfile()
{
	const double i = m_pulsarSpinAxisInclination;
	const double y = m_pulsarMagneticAxisInclination;
	const double deltaPhiOrb = m_orbitRotationDelta;
	const double deltaPhiRot = m_pulsarRotationDelta;
	const double rp = m_pulsarSemiMajorAxis;
	const double xk = m_cameraPosZ;
	const double yk = -m_cameraPosX;
	const double zk = -m_cameraPosY;
	const double cam = pow(xk,2) + pow(yk,2) + pow(zk,2);
	const double alpha = -m_mouseAngleH;
	const double delta = m_mouseAngleV;
	const double gaussProfile = 0.012337;

	for(int x = 0; x < 360; ++x) {
		// determine angle between pulsar's magnetic axis and line of sight
		const double phiOrb = x * deltaPhiOrb;
		const double phiRot = x * deltaPhiRot;

		double a = -sin(y) * sin(phiRot) * (xk + rp * cos(phiOrb)) \
				 + (cos(i) * sin(y) * cos(phiRot) + sin(i) * cos(y)) * (yk + rp * sin(phiOrb)) \
				 - (sin(i) * sin(y) * cos(phiRot) - cos(i) * cos(y)) * zk;

		double b = sqrt(pow(rp,2) + cam - 2 * sqrt(cam) * rp * cos(delta) * sin(alpha + phiOrb));

		// determine pulse amplitude
		double amp = exp(-2 * (1 - fabs(a/b)) / gaussProfile);

		// store amplitude
		m_pulseProfile[x] = (float) amp;
	}

	// propagate new profile
	emit pulseProfileUpdated(m_pulseProfile);
}