/****************************************************************************** * 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 . * * * ******************************************************************************/ #include "pulsaranimationwidget.h" PulsarAnimationWidget::PulsarAnimationWidget(QWidget *parent) : QGLWidget(parent), m_frameTimer(), m_pulsarSpinTimer(), m_orbitTimer() { connect(&m_frameTimer, SIGNAL(timeout()), this, SLOT(updateFrame())); connect(&m_pulsarSpinTimer, SIGNAL(timeout()), this, SLOT(updatePulsarSpin())); connect(&m_orbitTimer, SIGNAL(timeout()), this, SLOT(updateOrbit())); m_quadricPulsar = NULL; m_quadricPulsarCone1 = NULL; m_quadricPulsarCone2 = NULL; m_framesPerSecond = 25; setPulsarSpinFrequency(0.5f); m_pulsarRotationAngle = 0.0f; setOrbitFrequency(0.2f); setOrbitRadius(4.0f); m_orbitRotationAngle = 0.0f; m_mouseLastX = 0; m_mouseLastY = 0; m_mouseAngleH = 90; m_mouseAngleV = 30; 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.0 / m_framesPerSecond); m_pulsarSpinTimer.start(m_pulsarSpinFrequency); m_orbitTimer.start(m_orbitFrequency); } void PulsarAnimationWidget::pauseAnimation() { m_frameTimer.stop(); m_pulsarSpinTimer.stop(); m_orbitTimer.stop(); } void PulsarAnimationWidget::stopAnimation() { m_frameTimer.stop(); m_pulsarSpinTimer.stop(); m_orbitTimer.stop(); m_pulsarRotationAngle = 0.0; m_orbitRotationAngle = 0.0; updateGL(); } void PulsarAnimationWidget::updateFrame() { updateGL(); } void PulsarAnimationWidget::updatePulsarSpin() { if(m_pulsarRotationAngle <= 360.0) { m_pulsarRotationAngle++; } else { m_pulsarRotationAngle = 0.0; } } void PulsarAnimationWidget::updateOrbit() { if(m_orbitRotationAngle <= 360.0) { m_orbitRotationAngle++; } else { m_orbitRotationAngle = 0.0; } } 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(abs(angleV * deg2rad)) * zoom; updateGL(); } void PulsarAnimationWidget::setFramePerSecond(const unsigned int fps) { m_framesPerSecond = fps; } void PulsarAnimationWidget::setPulsarSpinFrequency(const float frequency) { m_pulsarSpinFrequency = (unsigned int) (1000 / (frequency * 360.0f)); m_pulsarSpinTimer.setInterval(m_pulsarSpinFrequency); } void PulsarAnimationWidget::setOrbitRadius(const float radius) { m_orbitRadius = radius; m_orbitRadiusNeg = -1.0 * radius; } void PulsarAnimationWidget::setOrbitFrequency(const float frequency) { m_orbitFrequency = (unsigned int) (1000 / (frequency * 360.0f)); m_orbitTimer.setInterval(m_orbitFrequency); }