pulsaranimationwidget.cpp 9.52 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

Oliver Bock's avatar
Oliver Bock committed
48
49
	setPulsarRotationDelta(0.5f);
	setOrbitRotationDelta(0.2f);
50
	setOrbitRadius(4.0f);
Oliver Bock's avatar
Oliver Bock committed
51
52

	m_pulsarRotationAngle = 0.0f;
53
	m_orbitRotationAngle = 0.0f;
54

55
	m_cameraInteraction = false;
56
57
	m_mouseLastX = 0;
	m_mouseLastY = 0;
Oliver Bock's avatar
Oliver Bock committed
58
59
	m_mouseAngleH = 90.0f;
	m_mouseAngleV = 30.f;
60
	m_cameraZoom = 15.0f;
61
62
63
	m_cameraZoomLBound = 2.0f;

	updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
Oliver Bock's avatar
Oliver Bock committed
64
65
66
67
}

PulsarAnimationWidget::~PulsarAnimationWidget()
{
68
	if(m_quadricPulsarOrbitPlane) gluDeleteQuadric(m_quadricPulsarOrbitPlane);
Oliver Bock's avatar
Oliver Bock committed
69
70
71
	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
72
73
74
75
}

void PulsarAnimationWidget::initializeGL()
{
Oliver Bock's avatar
Oliver Bock committed
76
77
78
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClearDepth(1.0f);
	glDepthFunc(GL_LEQUAL);
79
80
81
	glEnable(GL_DEPTH_TEST);

	glShadeModel(GL_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
82
83
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

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

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

102
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
103
	glEnable(GL_BLEND);
104
105

	m_quadricPulsarOrbitPlane = gluNewQuadric();
Oliver Bock's avatar
Oliver Bock committed
106
107
108
	m_quadricPulsar = gluNewQuadric();
    m_quadricPulsarCone1 = gluNewQuadric();
    m_quadricPulsarCone2 = gluNewQuadric();
109
    gluQuadricNormals(m_quadricPulsarOrbitPlane, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
110
111
112
    gluQuadricNormals(m_quadricPulsar, GLU_SMOOTH);
    gluQuadricNormals(m_quadricPulsarCone1, GLU_SMOOTH);
    gluQuadricNormals(m_quadricPulsarCone2, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
113
114
115
116
}

void PulsarAnimationWidget::resizeGL(int w, int h)
{
Oliver Bock's avatar
Oliver Bock committed
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
	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();

135
136
	gluLookAt(m_cameraPosX, m_cameraPosY, m_cameraPosZ,
			  0.0, 0.0, 0.0,
137
			  0.0, 1.0, 0.0);
Oliver Bock's avatar
Oliver Bock committed
138
139
140
141
142
143

	// 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 };
144

Oliver Bock's avatar
Oliver Bock committed
145
146
147
148
149
	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
150

Oliver Bock's avatar
Oliver Bock committed
151
	glPushMatrix();
152
153
154
155
		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
156
157
158
	glPopMatrix();

	glPushMatrix();
159
160
161
162
163
164
165
166
167
		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);
			gluSphere(m_quadricPulsar, 1.0f, 32, 32);
		glPopMatrix();

168
169
170
171
172
173
174
175
176
		// 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);

177
178
179
180
181
182
183
184
185
186
187
		glPushMatrix();
			glRotatef(m_pulsarRotationAngle-90, 0.0f, 1.0f, 0.0f);
			glTranslatef(0.0f, 0.0f, -4.0f);
			gluCylinder(m_quadricPulsarCone1, 0.5f, 0.0f, 3.0f, 32, 32);
		glPopMatrix();

		glPushMatrix();
			glRotatef(m_pulsarRotationAngle+90, 0.0f, 1.0f, 0.0f);
			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
188
	glPopMatrix();
189
190
191
192
193
194
195
196
197
198
199
200
201

	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
202
203
}

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

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

void PulsarAnimationWidget::stopAnimation()
{
	m_frameTimer.stop();
	m_pulsarRotationAngle = 0.0;
218
	m_orbitRotationAngle = 0.0;
Oliver Bock's avatar
Oliver Bock committed
219
220
221
222

	updateGL();
}

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

Oliver Bock's avatar
Oliver Bock committed
234
	updateGL();
235
236
}

237
238
239
240
241
242
void PulsarAnimationWidget::mousePressEvent(QMouseEvent *event)
{
	m_cameraInteraction = true;
	updateGL();
}

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
275
276
277
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)
{
	m_mouseLastX = 0;
	m_mouseLastY = 0;
278
279
	m_cameraInteraction = false;
	updateGL();
280
281
282
283
284
285
}

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

	updateGL();
}

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

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

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

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