Select Git revision
pulsaranimationwidget.cpp
pulsaranimationwidget.cpp 7.99 KiB
/******************************************************************************
* 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"
PulsarAnimationWidget::PulsarAnimationWidget(QWidget *parent) :
QGLWidget(parent),
m_frameTimer()
{
connect(&m_frameTimer, SIGNAL(timeout()), this, SLOT(updateFrame()));
m_quadricPulsar = NULL;
m_quadricPulsarCone1 = NULL;
m_quadricPulsarCone2 = NULL;
m_framesPerSecond = 25;
setPulsarRotationDelta(0.5f);
setOrbitRotationDelta(0.2f);
setOrbitRadius(4.0f);
m_pulsarRotationAngle = 0.0f;
m_orbitRotationAngle = 0.0f;
m_mouseLastX = 0;
m_mouseLastY = 0;
m_mouseAngleH = 90.0f;
m_mouseAngleV = 30.f;
m_cameraZoom = 10.0f;
m_cameraZoomLBound = 2.0f;
updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
}
PulsarAnimationWidget::~PulsarAnimationWidget()
{
if(m_quadricPulsar) gluDeleteQuadric(m_quadricPulsar);
if(m_quadricPulsarCone1) gluDeleteQuadric(m_quadricPulsarCone1);
if(m_quadricPulsarCone2) gluDeleteQuadric(m_quadricPulsarCone2);
}
void PulsarAnimationWidget::initializeGL()
{
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);
GLfloat LightAmbient[] = { 0.3f, 0.3f, 0.3f, 1.0f };
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);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 50.0);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 10.0);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
m_quadricPulsar = gluNewQuadric();
m_quadricPulsarCone1 = gluNewQuadric();
m_quadricPulsarCone2 = gluNewQuadric();
gluQuadricNormals(m_quadricPulsar, GLU_SMOOTH);
gluQuadricNormals(m_quadricPulsarCone1, GLU_SMOOTH);
gluQuadricNormals(m_quadricPulsarCone2, GLU_SMOOTH);
}
void PulsarAnimationWidget::resizeGL(int w, int h)
{
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();
gluLookAt(m_cameraPosX, m_cameraPosY, m_cameraPosZ,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
// 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);
glRotatef(m_orbitRotationAngle, 0.0f, 1.0f, 0.0f);
glPushMatrix();
glTranslatef(0.0f, 0.0f, m_orbitRadiusNeg);
gluSphere(m_quadricPulsar, 1.0f, 32, 32);
glPopMatrix();
glTranslatef(0.0f, 0.0f, m_orbitRadius);
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();
}
void PulsarAnimationWidget::runAnimation()
{
m_frameTimer.start(1000.0f / m_framesPerSecond);
}
void PulsarAnimationWidget::pauseAnimation()
{
m_frameTimer.stop();
}
void PulsarAnimationWidget::stopAnimation()
{
m_frameTimer.stop();
m_pulsarRotationAngle = 0.0;
m_orbitRotationAngle = 0.0;
updateGL();
}
void PulsarAnimationWidget::updateFrame()
{
m_pulsarRotationAngle += m_pulsarRotationDelta;
if(m_pulsarRotationAngle > 360) {
m_pulsarRotationAngle = 0.0f;
}
m_orbitRotationAngle += m_orbitRotationDelta;
if(m_orbitRotationAngle > 360) {
m_orbitRotationAngle = 0.0f;
}
updateGL();
}
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)
{
static const float deg2rad = PI/180.0f;
m_cameraPosX = sin(angleH * deg2rad) * zoom;
m_cameraPosY = sin(angleV * deg2rad) * zoom;
m_cameraPosZ = cos(angleH * deg2rad) * cos(fabs(angleV * deg2rad)) * zoom;
updateGL();
}
void PulsarAnimationWidget::setFramePerSecond(const unsigned int fps)
{
m_framesPerSecond = fps;
}
void PulsarAnimationWidget::setPulsarRotationDelta(const float frequency)
{
m_pulsarRotationDelta = (360.0f * frequency) / m_framesPerSecond;
}
void PulsarAnimationWidget::setOrbitRotationDelta(const float frequency)
{
m_orbitRotationDelta = (360.0f * frequency) / m_framesPerSecond;
}
void PulsarAnimationWidget::setOrbitRadius(const float radius)
{
m_orbitRadius = radius;
m_orbitRadiusNeg = -1.0 * radius;
}