pulsaranimationwidget.cpp 10 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),
Oliver Bock's avatar
Oliver Bock committed
27
	m_frameTimer()
Oliver Bock's avatar
Oliver Bock committed
28
{
29
30
31
32
33
34
	if(!format().rgba()) {
		qWarning("Sorry, no RGBA support...");
	}
	if(!format().alpha()) {
		qWarning("Sorry, no alpha channel support...");
	}
Oliver Bock's avatar
Oliver Bock committed
35
36
37
	if(!format().sampleBuffers()) {
		qWarning("Sorry, no multisampling support...");
	}
38

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

41
    m_quadricPulsarOrbitPlane = NULL;
42
43
44
	m_quadricPulsar = NULL;
	m_quadricPulsarCone1 = NULL;
	m_quadricPulsarCone2 = NULL;
Oliver Bock's avatar
Oliver Bock committed
45
46

	m_framesPerSecond = 25;
47

48
	resetParameters();
49

50
	m_cameraInteraction = false;
51
52
	m_mouseLastX = 0;
	m_mouseLastY = 0;
Oliver Bock's avatar
Oliver Bock committed
53
54
	m_mouseAngleH = 90.0f;
	m_mouseAngleV = 30.f;
55
	m_cameraZoom = 15.0f;
56
57
58
	m_cameraZoomLBound = 2.0f;

	updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
Oliver Bock's avatar
Oliver Bock committed
59
60
61
62
}

PulsarAnimationWidget::~PulsarAnimationWidget()
{
63
	if(m_quadricPulsarOrbitPlane) gluDeleteQuadric(m_quadricPulsarOrbitPlane);
Oliver Bock's avatar
Oliver Bock committed
64
65
66
	if(m_quadricPulsar) gluDeleteQuadric(m_quadricPulsar);
	if(m_quadricPulsarCone1) gluDeleteQuadric(m_quadricPulsarCone1);
	if(m_quadricPulsarCone2) gluDeleteQuadric(m_quadricPulsarCone2);
Oliver Bock's avatar
Oliver Bock committed
67
68
69
70
}

void PulsarAnimationWidget::initializeGL()
{
Oliver Bock's avatar
Oliver Bock committed
71
72
73
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClearDepth(1.0f);
	glDepthFunc(GL_LEQUAL);
74
75
76
	glEnable(GL_DEPTH_TEST);

	glShadeModel(GL_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
77
78
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

79
	GLfloat LightAmbient[] = { 0.3f, 0.3f, 0.3f, 1.0f };
Oliver Bock's avatar
Oliver Bock committed
80
81
82
83
84
85
86
87
88
	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);
89
	glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 50.0);
Oliver Bock's avatar
Oliver Bock committed
90
	glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
91
	glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 10.0);
Oliver Bock's avatar
Oliver Bock committed
92
93
94
95

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

97
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
98
	glEnable(GL_BLEND);
99
100

	m_quadricPulsarOrbitPlane = gluNewQuadric();
Oliver Bock's avatar
Oliver Bock committed
101
102
103
	m_quadricPulsar = gluNewQuadric();
    m_quadricPulsarCone1 = gluNewQuadric();
    m_quadricPulsarCone2 = gluNewQuadric();
104
    gluQuadricNormals(m_quadricPulsarOrbitPlane, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
105
106
107
    gluQuadricNormals(m_quadricPulsar, GLU_SMOOTH);
    gluQuadricNormals(m_quadricPulsarCone1, GLU_SMOOTH);
    gluQuadricNormals(m_quadricPulsarCone2, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
108
109
110
111
}

void PulsarAnimationWidget::resizeGL(int w, int h)
{
Oliver Bock's avatar
Oliver Bock committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45.0f, (GLfloat)w / (GLfloat)h, 0.1f, 100.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

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

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

130
131
	gluLookAt(m_cameraPosX, m_cameraPosY, m_cameraPosZ,
			  0.0, 0.0, 0.0,
132
			  0.0, 1.0, 0.0);
Oliver Bock's avatar
Oliver Bock committed
133
134
135
136
137
138

	// 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 };
	static GLfloat low_shininess[] = { 5.0 };
139

Oliver Bock's avatar
Oliver Bock committed
140
141
142
143
144
	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
145

Oliver Bock's avatar
Oliver Bock committed
146
	glPushMatrix();
147
148
149
150
		glTranslatef(sin((m_orbitRotationAngle + 180) * deg2rad) * m_companionOrbitRadius,
					 0.0f,
					 cos((m_orbitRotationAngle + 180) * deg2rad) * m_companionOrbitRadius);
		gluSphere(m_quadricPulsar, 1.0f, 32, 32);
Oliver Bock's avatar
Oliver Bock committed
151
152
153
	glPopMatrix();

	glPushMatrix();
154
155
156
157
158
159
		glTranslatef(sin(m_orbitRotationAngle * deg2rad) * m_pulsarOrbitRadius,
					 0.0f,
					 cos(m_orbitRotationAngle * deg2rad) * m_pulsarOrbitRadius);

		glPushMatrix();
			glRotatef(m_pulsarRotationAngle, 0.0f, 1.0f, 0.0f);
160
			glRotatef(m_pulsarSpinAxisInclination, 1.0f, 0.0f, 0.0f);
161
162
163
			gluSphere(m_quadricPulsar, 1.0f, 32, 32);
		glPopMatrix();

164
165
166
167
168
169
170
171
172
		// 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_AMBIENT, coneAmbient);
		glMaterialfv(GL_FRONT, GL_DIFFUSE, coneDiffuse);
		glMaterialfv(GL_FRONT, GL_SPECULAR, coneSpecular);

173
		glPushMatrix();
174
			glRotatef(m_pulsarRotationAngle - 90.0f, 0.0f, 1.0f, 0.0f);
175
			glRotatef(-m_pulsarMagneticAxisInclination - m_pulsarSpinAxisInclination + 90.0f, 1.0f, 0.0f, 0.0f);
176
177
178
179
180
			glTranslatef(0.0f, 0.0f, -4.0f);
			gluCylinder(m_quadricPulsarCone1, 0.5f, 0.0f, 3.0f, 32, 32);
		glPopMatrix();

		glPushMatrix();
181
			glRotatef(m_pulsarRotationAngle + 90.0f, 0.0f, 1.0f, 0.0f);
182
			glRotatef(m_pulsarMagneticAxisInclination + m_pulsarSpinAxisInclination - 90.0f, 1.0f, 0.0f, 0.0f);
183
184
185
			glTranslatef(0.0f, 0.0f, -4.0f);
			gluCylinder(m_quadricPulsarCone2, 0.5f, 0.0f, 3.0f, 32, 32);
		glPopMatrix();
Oliver Bock's avatar
Oliver Bock committed
186
	glPopMatrix();
187
188
189
190
191
192
193
194
195
196
197
198
199

	if(m_cameraInteraction) {
		static GLfloat pulsarOrbitAmbientDiffuse[] = { 1.0, 1.0, 1.0, 0.33 };
		glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, pulsarOrbitAmbientDiffuse);

		glPushMatrix();
			glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
			gluDisk(m_quadricPulsarOrbitPlane,
					m_pulsarOrbitRadius * 0.9f,
					m_pulsarOrbitRadius * 1.1f,
					64, 1);
		glPopMatrix();
	}
Oliver Bock's avatar
Oliver Bock committed
200
201
}

Oliver Bock's avatar
Oliver Bock committed
202
203
void PulsarAnimationWidget::runAnimation()
{
Oliver Bock's avatar
Oliver Bock committed
204
	m_frameTimer.start(1000.0f / m_framesPerSecond);
Oliver Bock's avatar
Oliver Bock committed
205
}
Oliver Bock's avatar
Oliver Bock committed
206

Oliver Bock's avatar
Oliver Bock committed
207
208
209
210
211
212
213
214
void PulsarAnimationWidget::pauseAnimation()
{
	m_frameTimer.stop();
}

void PulsarAnimationWidget::stopAnimation()
{
	m_frameTimer.stop();
215
	resetParameters();
Oliver Bock's avatar
Oliver Bock committed
216
217
218
219

	updateGL();
}

Oliver Bock's avatar
Oliver Bock committed
220
void PulsarAnimationWidget::updateFrame()
Oliver Bock's avatar
Oliver Bock committed
221
{
Oliver Bock's avatar
Oliver Bock committed
222
223
224
	m_pulsarRotationAngle += m_pulsarRotationDelta;
	if(m_pulsarRotationAngle > 360) {
		m_pulsarRotationAngle = 0.0f;
Oliver Bock's avatar
Oliver Bock committed
225
	}
Oliver Bock's avatar
Oliver Bock committed
226
227
228
	m_orbitRotationAngle += m_orbitRotationDelta;
	if(m_orbitRotationAngle > 360) {
		m_orbitRotationAngle = 0.0f;
Oliver Bock's avatar
Oliver Bock committed
229
230
	}

Oliver Bock's avatar
Oliver Bock committed
231
	updateGL();
232
233
}

234
235
void PulsarAnimationWidget::mousePressEvent(QMouseEvent *event)
{
236
237
	Q_UNUSED(event);

238
239
240
241
	m_cameraInteraction = true;
	updateGL();
}

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
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;
			m_mouseAngleH = m_mouseAngleH < 360? m_mouseAngleH : 0;

		}
		if(m_mouseLastY != 0) {
			m_mouseAngleV -= (m_mouseLastY - event->y()) / 2;
			m_mouseAngleV = m_mouseAngleV < 90? m_mouseAngleV : 90;
			m_mouseAngleV = m_mouseAngleV > -90? m_mouseAngleV : -90;
		}

		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;
			m_cameraZoom = m_cameraZoom >= m_cameraZoomLBound? m_cameraZoom : m_cameraZoomLBound;
			updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
		}

		m_mouseLastY = event->y();
	}

	updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
}

void PulsarAnimationWidget::mouseReleaseEvent(QMouseEvent *event)
{
275
276
	Q_UNUSED(event);

277
278
	m_mouseLastX = 0;
	m_mouseLastY = 0;
279
280
	m_cameraInteraction = false;
	updateGL();
281
282
283
284
285
286
}

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
287
	m_cameraPosZ = cos(angleH * deg2rad) * cos(fabs(angleV * deg2rad)) * zoom;
288
289
290
291

	updateGL();
}

Oliver Bock's avatar
Oliver Bock committed
292
293
294
295
296
void PulsarAnimationWidget::setFramePerSecond(const unsigned int fps)
{
	m_framesPerSecond = fps;
}

Oliver Bock's avatar
Oliver Bock committed
297
void PulsarAnimationWidget::setPulsarRotationDelta(const float frequency)
Oliver Bock's avatar
Oliver Bock committed
298
{
Oliver Bock's avatar
Oliver Bock committed
299
	m_pulsarRotationDelta = (360.0f * frequency) / m_framesPerSecond;
Oliver Bock's avatar
Oliver Bock committed
300
}
301

Oliver Bock's avatar
Oliver Bock committed
302
void PulsarAnimationWidget::setOrbitRotationDelta(const float frequency)
303
{
Oliver Bock's avatar
Oliver Bock committed
304
	m_orbitRotationDelta = (360.0f * frequency) / m_framesPerSecond;
305
306
}

Oliver Bock's avatar
Oliver Bock committed
307
void PulsarAnimationWidget::setOrbitRadius(const float radius)
308
{
309
310
311
	// for the time being both have the same orbit (mass)
	m_pulsarOrbitRadius = radius;
	m_companionOrbitRadius = radius;
312
}
313

314
315
316
317
318
319
320
void PulsarAnimationWidget::setPulsarSpinAxisInclination(const int degrees)
{
	m_pulsarSpinAxisInclination = degrees;

	updateGL();
}

321
322
323
324
325
326
void PulsarAnimationWidget::setPulsarMagneticAxisInclination(const int degrees)
{
	m_pulsarMagneticAxisInclination = degrees;

	updateGL();
}
327
328
329
330
331
332

void PulsarAnimationWidget::resetParameters()
{
	m_pulsarRotationAngle = 0.0f;
	m_orbitRotationAngle = 0.0f;
}