pulsaranimationwidget.cpp 8.3 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 26
PulsarAnimationWidget::PulsarAnimationWidget(QWidget *parent) :
	QGLWidget(parent),
Oliver Bock's avatar
Oliver Bock committed
27
	m_frameTimer()
Oliver Bock's avatar
Oliver Bock committed
28
{
Oliver Bock's avatar
Oliver Bock committed
29
    connect(&m_frameTimer, SIGNAL(timeout()), this, SLOT(updateFrame()));
Oliver Bock's avatar
Oliver Bock committed
30

31 32 33
	m_quadricPulsar = NULL;
	m_quadricPulsarCone1 = NULL;
	m_quadricPulsarCone2 = NULL;
Oliver Bock's avatar
Oliver Bock committed
34 35

	m_framesPerSecond = 25;
36

Oliver Bock's avatar
Oliver Bock committed
37 38
	setPulsarRotationDelta(0.5f);
	setOrbitRotationDelta(0.2f);
39
	setOrbitRadius(4.0f);
Oliver Bock's avatar
Oliver Bock committed
40 41

	m_pulsarRotationAngle = 0.0f;
42
	m_orbitRotationAngle = 0.0f;
43 44 45

	m_mouseLastX = 0;
	m_mouseLastY = 0;
Oliver Bock's avatar
Oliver Bock committed
46 47
	m_mouseAngleH = 90.0f;
	m_mouseAngleV = 30.f;
48 49 50 51
	m_cameraZoom = 10.0f;
	m_cameraZoomLBound = 2.0f;

	updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
Oliver Bock's avatar
Oliver Bock committed
52 53 54 55
}

PulsarAnimationWidget::~PulsarAnimationWidget()
{
Oliver Bock's avatar
Oliver Bock committed
56 57 58
	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
59 60 61 62
}

void PulsarAnimationWidget::initializeGL()
{
Oliver Bock's avatar
Oliver Bock committed
63 64 65 66 67 68 69
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

70
	GLfloat LightAmbient[] = { 0.3f, 0.3f, 0.3f, 1.0f };
Oliver Bock's avatar
Oliver Bock committed
71 72 73 74 75 76 77 78 79
	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);
80
	glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 50.0);
Oliver Bock's avatar
Oliver Bock committed
81
	glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
82
	glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 10.0);
Oliver Bock's avatar
Oliver Bock committed
83 84 85 86

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

Oliver Bock's avatar
Oliver Bock committed
88 89 90 91 92 93
	m_quadricPulsar = gluNewQuadric();
    m_quadricPulsarCone1 = gluNewQuadric();
    m_quadricPulsarCone2 = gluNewQuadric();
    gluQuadricNormals(m_quadricPulsar, GLU_SMOOTH);
    gluQuadricNormals(m_quadricPulsarCone1, GLU_SMOOTH);
    gluQuadricNormals(m_quadricPulsarCone2, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
94 95 96 97
}

void PulsarAnimationWidget::resizeGL(int w, int h)
{
Oliver Bock's avatar
Oliver Bock committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
	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();

116 117
	gluLookAt(m_cameraPosX, m_cameraPosY, m_cameraPosZ,
			  0.0, 0.0, 0.0,
118
			  0.0, 1.0, 0.0);
Oliver Bock's avatar
Oliver Bock committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

	// TODO: should be located elsewhere
	static GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
	static GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 };
	static GLfloat mat_ambient_color[] = { 0.8, 0.8, 0.2, 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 no_shininess[] = { 0.0 };
	static GLfloat low_shininess[] = { 5.0 };
	static GLfloat high_shininess[] = { 100.0 };
	static GLfloat mat_emission[] = { 0.3, 0.2, 0.2, 0.0 };
	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
135

Oliver Bock's avatar
Oliver Bock committed
136
	glPushMatrix();
137 138 139 140
		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
141 142 143
	glPopMatrix();

	glPushMatrix();
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
		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();

		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
164
	glPopMatrix();
Oliver Bock's avatar
Oliver Bock committed
165 166
}

Oliver Bock's avatar
Oliver Bock committed
167 168
void PulsarAnimationWidget::runAnimation()
{
Oliver Bock's avatar
Oliver Bock committed
169
	m_frameTimer.start(1000.0f / m_framesPerSecond);
Oliver Bock's avatar
Oliver Bock committed
170
}
Oliver Bock's avatar
Oliver Bock committed
171

Oliver Bock's avatar
Oliver Bock committed
172 173 174 175 176 177 178 179 180
void PulsarAnimationWidget::pauseAnimation()
{
	m_frameTimer.stop();
}

void PulsarAnimationWidget::stopAnimation()
{
	m_frameTimer.stop();
	m_pulsarRotationAngle = 0.0;
181
	m_orbitRotationAngle = 0.0;
Oliver Bock's avatar
Oliver Bock committed
182 183 184 185

	updateGL();
}

Oliver Bock's avatar
Oliver Bock committed
186
void PulsarAnimationWidget::updateFrame()
Oliver Bock's avatar
Oliver Bock committed
187
{
Oliver Bock's avatar
Oliver Bock committed
188 189 190
	m_pulsarRotationAngle += m_pulsarRotationDelta;
	if(m_pulsarRotationAngle > 360) {
		m_pulsarRotationAngle = 0.0f;
Oliver Bock's avatar
Oliver Bock committed
191
	}
Oliver Bock's avatar
Oliver Bock committed
192 193 194
	m_orbitRotationAngle += m_orbitRotationDelta;
	if(m_orbitRotationAngle > 360) {
		m_orbitRotationAngle = 0.0f;
Oliver Bock's avatar
Oliver Bock committed
195 196
	}

Oliver Bock's avatar
Oliver Bock committed
197
	updateGL();
198 199
}

200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
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;
}

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
241
	m_cameraPosZ = cos(angleH * deg2rad) * cos(fabs(angleV * deg2rad)) * zoom;
242 243 244 245

	updateGL();
}

Oliver Bock's avatar
Oliver Bock committed
246 247 248 249 250
void PulsarAnimationWidget::setFramePerSecond(const unsigned int fps)
{
	m_framesPerSecond = fps;
}

Oliver Bock's avatar
Oliver Bock committed
251
void PulsarAnimationWidget::setPulsarRotationDelta(const float frequency)
Oliver Bock's avatar
Oliver Bock committed
252
{
Oliver Bock's avatar
Oliver Bock committed
253
	m_pulsarRotationDelta = (360.0f * frequency) / m_framesPerSecond;
Oliver Bock's avatar
Oliver Bock committed
254
}
255

Oliver Bock's avatar
Oliver Bock committed
256
void PulsarAnimationWidget::setOrbitRotationDelta(const float frequency)
257
{
Oliver Bock's avatar
Oliver Bock committed
258
	m_orbitRotationDelta = (360.0f * frequency) / m_framesPerSecond;
259 260
}

Oliver Bock's avatar
Oliver Bock committed
261
void PulsarAnimationWidget::setOrbitRadius(const float radius)
262
{
263 264 265
	// for the time being both have the same orbit (mass)
	m_pulsarOrbitRadius = radius;
	m_companionOrbitRadius = radius;
266
}