Skip to content
Snippets Groups Projects
Select Git revision
  • 123fcd36aa81ae4b7c16b827fd041dfdeb2d3c5b
  • master default
  • mingw_gcc44
  • release_ABP1_012
  • release_ABP1_008
  • release_ABP1_006
  • release_ABP1_007
  • release_ABP1_005
  • release_ABP1_004
  • release_ABP1_003
  • pre_release_0.15
  • release_ABP1_001
  • release_ABP1_002
  • pre_release_0.13
  • pre_release_0.14
  • pre_release_0.11
  • pre_release_0.12
  • pre_release_0.10
  • pre_release_0.09
  • pre_release_0.08
20 results

header.html

Blame
  • Forked from einsteinathome / graphicsframework
    Source project has a limited visibility.
    pulsaranimationwidget.cpp 17.61 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"
    
    const double PulsarAnimationWidget::deg2rad = PI/180.0;
    
    PulsarAnimationWidget::PulsarAnimationWidget(QWidget *parent) :
        QGLWidget(QGLFormat(QGL::AlphaChannel | QGL::SampleBuffers), parent),
    
        m_pulseProfile(360, 0.0)
    {
        QString msgThis = tr("3D animation");
        if(!format().directRendering()) {
            QString msg = tr("Sorry, no direct rendering support for %1...");
            qWarning() << msg.arg(msgThis);
        }
        if(!format().doubleBuffer()) {
            QString msg = tr("Sorry, no double buffering support for %1...");
            qWarning() << msg.arg(msgThis);
        }
        if(!format().rgba()) {
            QString msg = tr("Sorry, no RGBA support for %1...");
            qWarning() << msg.arg(msgThis);
        }
        if(!format().alpha()) {
            QString msg = tr("Sorry, no alpha channel support for %1...");
            qWarning() << msg.arg(msgThis);
        }
        if(!format().sampleBuffers()) {
            QString msg = tr("Sorry, no multisampling support for %1...");
            qWarning() << msg.arg(msgThis);
        }
    
        // initialize quadric pointers
        m_quadricVirgoh = NULL;
        m_quadricVirgov = NULL;
        m_quadricEarth = NULL;
        m_quadricLLOh = NULL;
        m_quadricLLOv = NULL;
        m_quadricSourcePlane = NULL;
        m_quadricSourcePlaneNormal = NULL;
        m_quadricSourcePlaneNormalCap = NULL;
        m_quadricLHOv = NULL;
        m_quadricLHOh = NULL;
    
        // initialize texture pointers
        m_beamTexture = 0;
    
        // initial parameters (have to match GUI!)
        m_LHOAngle = 180;
        m_LLOAngle = -100;
        m_VirgoAngle = 165;
        m_sourceIota = 0.0;
        m_sourceInclination = 0;
    
        m_earthRadius = 3.0;
    
        // initial view features
        m_cameraInteraction = false;
    
        // initial view settings
        m_mouseAngleH = 0.0;
        m_mouseAngleV = 0.0;
        m_cameraZoom = 100.0;
        m_cameraZoomLBound = 10.0;
        m_cameraZoomUBound = 4500.0;
        m_mouseLastX = 0;
        m_mouseLastY = 0;
    
        // update camera based on settings above
        updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
    }
    
    PulsarAnimationWidget::~PulsarAnimationWidget()
    {
        if(m_quadricVirgoh) gluDeleteQuadric(m_quadricVirgoh);
        if(m_quadricVirgov) gluDeleteQuadric(m_quadricVirgov);
        if(m_quadricEarth) gluDeleteQuadric(m_quadricEarth);
        if(m_quadricLLOh) gluDeleteQuadric(m_quadricLLOh);
        if(m_quadricLLOv) gluDeleteQuadric(m_quadricLLOv);
        if(m_quadricSourcePlane) gluDeleteQuadric(m_quadricSourcePlane);
        if(m_quadricSourcePlaneNormal) gluDeleteQuadric(m_quadricSourcePlaneNormal);
        if(m_quadricSourcePlaneNormalCap) gluDeleteQuadric(m_quadricSourcePlaneNormalCap);
        if(m_quadricLHOv) gluDeleteQuadric(m_quadricLHOv);
        if(m_quadricLHOh) gluDeleteQuadric(m_quadricLHOh);
    
        if(m_beamTexture) deleteTexture(m_beamTexture);
    }
    
    void PulsarAnimationWidget::initializeGL()
    {
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClearDepth(1.0);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_DEPTH_TEST);
    
        glShadeModel(GL_SMOOTH);
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    
        GLfloat LightAmbient[] = {0.3, 0.3, 0.3, 1.0};
        GLfloat LightDiffuse[] = {1.0, 1.0, 1.0, 1.0};
        GLfloat LightSpecular[] = {1.0, 1.0, 1.0, 1.0};
        GLfloat LightPosition[] = {0.0, 0.0, 3.0, 1.0};
        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);
    
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
    
        m_quadricVirgoh = gluNewQuadric();
        m_quadricVirgov = gluNewQuadric();
        m_quadricEarth = gluNewQuadric();
        m_quadricLLOh = gluNewQuadric();
        m_quadricLLOv = gluNewQuadric();
        m_quadricSourcePlane = gluNewQuadric();
        m_quadricSourcePlaneNormal = gluNewQuadric();
        m_quadricSourcePlaneNormalCap = gluNewQuadric();
        m_quadricLHOv = gluNewQuadric();
        m_quadricLHOh = gluNewQuadric();
    
        gluQuadricNormals(m_quadricVirgoh, GLU_SMOOTH);
        gluQuadricNormals(m_quadricVirgov, GLU_SMOOTH);
        gluQuadricNormals(m_quadricEarth, GLU_SMOOTH);
        gluQuadricNormals(m_quadricLLOh, GLU_SMOOTH);
        gluQuadricNormals(m_quadricLLOv, GLU_SMOOTH);
        gluQuadricNormals(m_quadricSourcePlane, GLU_SMOOTH);
        gluQuadricNormals(m_quadricSourcePlaneNormal, GLU_SMOOTH);
        gluQuadricNormals(m_quadricSourcePlaneNormalCap, GLU_SMOOTH);
        gluQuadricNormals(m_quadricLHOv, GLU_SMOOTH);
        gluQuadricNormals(m_quadricLHOh, GLU_SMOOTH);
    
        // query max texture size (estimate)
        GLint maxTextureSize;
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
    
        // prepare and check beam texture
        QImage beamTexture(":/textures/resources/World-Map-7.jpg");
    
        // bind textures
        m_beamTexture = bindTexture(beamTexture, GL_TEXTURE_2D, GL_RGBA);
    
        // use mipmapped textures
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    }
    
    void PulsarAnimationWidget::resizeGL(int w, int h)
    {
        glViewport(0, 0, w, h);
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        gluPerspective(4.5, (GLfloat)w / (GLfloat)h, 0.1, 5000.0);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }
    
    void PulsarAnimationWidget::paintGL()
    {
        GLfloat x,y,angle;
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        // TODO: should be located elsewhere
        static GLfloat no_mat[] = {0.0, 0.0, 0.0, 1.0};
        static GLfloat mat_diffuse[] = {0.0, 0.0, 0.5, 1.0};
        static GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
        static GLfloat low_shininess[] = {2.5};
        static GLfloat translucent[] = {1.0, 1.0, 1.0, 0.33};
    
        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);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
        gluLookAt(m_cameraPosX, m_cameraPosY, m_cameraPosZ,
                  0.0, 0.0, 0.0,
                  0.0, 1.0, 0.0);
    
        // save current state (the following is using parallel projection)
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        {
            glLoadIdentity();
            glOrtho(0, width(), 0, height(), 0.1, 501.0);
            glMatrixMode(GL_MODELVIEW);
            glPushMatrix();
            {
                glLoadIdentity();
    
                // draw backdrop (independent parallel projection)
                glColor3f(1.0, 1.0, 1.0f);
                glTranslatef(0.0, 0.0, -501.0);
    
                // restore original state
                glMatrixMode(GL_PROJECTION);
            }
            glPopMatrix();
            glMatrixMode(GL_MODELVIEW);
        }
        glPopMatrix();
    
        // draw earth
        glPushMatrix();
        {
            glRotatef(130, 0.0, 1.0, 0.0);
            glPushMatrix();
            {
                glRotatef(90, 1.0, 0.0, 0.0);
                glRotatef(180, 1.0, 1.0, 0.0);
    
                // create texture coordinates and enable texturing
                gluQuadricTexture(m_quadricEarth, GL_TRUE);
                glBindTexture(GL_TEXTURE_2D, m_beamTexture);
                glEnable(GL_TEXTURE_2D);
    
                gluSphere(m_quadricEarth, m_earthRadius, 32, 32);
            }
            glPopMatrix();
        }
        glPopMatrix();
    
        // draw LHO
        glPushMatrix();
        {
            glColor3f(1.0f, 1.0f, 1.0f);
    
            glRotatef(-81, 1.0, 1.0, 0.0);
            glTranslatef(0.0, 0.0, m_earthRadius);
            glRotatef(m_LHOAngle, 0.0, 0.0, 1.0);
            glPushMatrix();
            {
                glRotatef(90, 0.0, 1.0, 0.0);
                gluCylinder(m_quadricLHOh, 0.010, 0.010, 0.20, 32, 1);
            }
            glPopMatrix();
    
            glPushMatrix();
            {
                glRotatef(90, 0.0, 1.0, 0.0);
                glRotatef(90, 1.0, 0.0, 0.0);
                glColor3f(0.5f, 0.5f, 1.0f);
                gluCylinder(m_quadricLHOv, 0.010, 0.010, 0.20, 32, 1);
            }
            glPopMatrix();
        }
        glPopMatrix();
    
        // draw LLO
        glPushMatrix();
        {
            glColor3f(1.0f, 1.0f, 1.0f);
    
            glRotatef(-2, 0.0, 1.0, 0.0);
            glRotatef(5, 1.0, 0.0, 0.0);
            glRotatef(-60, 1.0, 1.0, 0.0);
            glTranslatef(0.0, 0.0, m_earthRadius);
            glRotatef(m_LLOAngle, 0.0, 0.0, 1.0);
            glPushMatrix();
            {
                glRotatef(90, 0.0, 1.0, 0.0);
                gluCylinder(m_quadricLLOh, 0.010, 0.010, 0.20, 32, 1);
            }
            glPopMatrix();
    
            glPushMatrix();
            {
                glRotatef(90, 0.0, 1.0, 0.0);
                glRotatef(90, 1.0, 0.0, 0.0);
                glColor3f(1.0f, 0.5f, 0.5f);
                gluCylinder(m_quadricLLOv, 0.010, 0.010, 0.20, 32, 1);
            }
            glPopMatrix();
        }
        glPopMatrix();
    
        // draw Virgo
        glPushMatrix();
        {
            glColor3f(1.0f, 1.0f, 1.0f);
    
            glRotatef(50, 0.0, 1.0, 0.0);
            glRotatef(-43, 1.0, 0.0, 0.0);
            glTranslatef(0.0, 0.0, m_earthRadius);
            glRotatef(m_VirgoAngle, 0.0, 0.0, 1.0);
            glPushMatrix();
            {
                glRotatef(90, 0.0, 1.0, 0.0);
                gluCylinder(m_quadricVirgoh, 0.010, 0.010, 0.20, 32, 1);
            }
            glPopMatrix();
    
            glPushMatrix();
            {
                glRotatef(90, 0.0, 1.0, 0.0);
                glRotatef(90, 1.0, 0.0, 0.0);
                glColor3f(0.5f, 1.0f, 0.5f);
                gluCylinder(m_quadricVirgov, 0.010, 0.010, 0.20, 32, 1);
            }
            glPopMatrix();
        }
        glPopMatrix();
    
        // draw source
        glPushMatrix();
        {
            glTranslatef(3.0,
                         3.0,
                         -3.0);
    
            glRotatef(m_sourceInclination, 0.0, 1.0, 0.0);
            glRotatef(-45, 0.0, 1.0, 0.0);
            glRotatef(90, 1.0, 0.0, 0.0);
    
            glPushMatrix();
            {
                glRotatef(m_sourceIota, 1.0, 0.0, 0.0);
                glRotatef(-45, 1.0, 0.0, 0.0);
    
                // draw source plane normal
                glColor3f(1.0f, 0.0f, 0.0f);
                glPushMatrix();
                {
                    glTranslatef(0.0, 0.0, -1.0);
                    gluCylinder(m_quadricSourcePlaneNormal, 0.020, 0.020, 1.5, 32, 1);
                }
                glPopMatrix();
                glPushMatrix();
                {
                    glTranslatef(0.0, 0.0, -1.0);
                    gluDisk(m_quadricSourcePlaneNormalCap, 0, 0.020, 32, 8);
                }
                glPopMatrix();
                glPushMatrix();
                {
                    glTranslatef(0.0, 0.0, 0.5f);
                    glBegin(GL_TRIANGLE_FAN);
                    {
                        // Pinnacle of cone is shared vertex for fan, moved up z-axis
                        // to produce a cone instead of a circle
                        glVertex3f(0.0f, 0.0f, 0.5f);
    
                        // Loop around in a circle and specify even points along the circle
                        // as the vertices of the triangle fan (32 sections)
                        for(angle = 0.0f; angle < (2.0f*PI); angle += (PI/32.0f))
                        {
                            // Calculate x and y position of the next vertex
                            x = 0.1f * sin(angle);
                            y = 0.1f * cos(angle);
    
                            // Specify the next vertex for the triangle fan
                            glVertex2f(x, y);
                        }
                    }
                    glEnd();
                }
                glPopMatrix();
    
                // draw disc
                glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, translucent);
                glEnable(GL_LIGHTING);
    
                glPushMatrix();
                {
                    gluDisk(m_quadricSourcePlane,
                            0,
                            1.0,
                            64, 1);
                }
                glPopMatrix();
    
                glDisable(GL_LIGHTING);
            }
            glPopMatrix();
        }
        glPopMatrix();
    
        // save current state (the following is using parallel projection)
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        {
            glLoadIdentity();
            glOrtho(0, width(), 0, height(), 0.1, 501.0);
            glMatrixMode(GL_MODELVIEW);
            glPushMatrix();
            {
                glLoadIdentity();
    
                // draw copyright info last (appears in front of everything)
                glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
                QFont font;
                font.setPointSize(11);
                font.setBold(true);
                font.setFamily("Arial");
                font.setStyleStrategy((QFont::StyleStrategy) (QFont::OpenGLCompatible | QFont::PreferQuality));
                renderText(10, 25, -100, QString("Copyright %1 2017").arg(QChar(0x00A9)), font);
                renderText(10, 10, -100, tr("Max Planck Institute for Gravitational Physics"), font);
    
                // restore original state
                glMatrixMode(GL_PROJECTION);
            }
            glPopMatrix();
            glMatrixMode(GL_MODELVIEW);
        }
        glPopMatrix();
    }
    
    void PulsarAnimationWidget::mousePressEvent(QMouseEvent *event)
    {
        Q_UNUSED(event);
    
        m_cameraInteraction = true;
        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());
                m_mouseAngleH = m_mouseAngleH < 360 ? m_mouseAngleH : 0;
                m_mouseAngleH = m_mouseAngleH >=  0 ? m_mouseAngleH : 359;
            }
            if(m_mouseLastY != 0) {
                m_mouseAngleV -= (m_mouseLastY - event->y());
                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());
                m_cameraZoom = m_cameraZoom >= m_cameraZoomLBound ? m_cameraZoom : m_cameraZoomLBound;
                m_cameraZoom = m_cameraZoom >= m_cameraZoomUBound ? m_cameraZoomUBound : m_cameraZoom;
            }
    
            m_mouseLastY = event->y();
        }
    
        updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
    }
    
    void PulsarAnimationWidget::mouseReleaseEvent(QMouseEvent *event)
    {
        Q_UNUSED(event);
    
        m_mouseLastX = 0;
        m_mouseLastY = 0;
        m_cameraInteraction = false;
    
        updateGL();
    }
    
    void PulsarAnimationWidget::showEvent(QShowEvent *event)
    {
        Q_UNUSED(event);
    
        // update and propagate pulse profile
        updatePulseProfile();
    }
    
    void PulsarAnimationWidget::updateCameraPosition(const double angleH, const double angleV, const double zoom)
    {
        m_cameraPosX = sin(angleH * deg2rad) * cos(angleV * deg2rad) * zoom;
        m_cameraPosY = sin(angleV * deg2rad) * zoom;
        m_cameraPosZ = cos(angleH * deg2rad) * cos(angleV * deg2rad) * zoom;
    
        updatePulseProfile();
    
        updateGL();
    }
    
    void PulsarAnimationWidget::setSourceInclination(const double degrees)
    {
        m_sourceInclination = degrees;
        updatePulseProfile();
    
        updateGL();
    }
    
    void PulsarAnimationWidget::setLHOAngle(const double degrees)
    {
        m_LHOAngle = degrees + 180;
        updatePulseProfile();
    
        updateGL();
    }
    
    void PulsarAnimationWidget::setLLOAngle(const double degrees)
    {
        m_LLOAngle = degrees - 100;
        updatePulseProfile();
    
        updateGL();
    }
    
    void PulsarAnimationWidget::setVirgoAngle(const int degrees)
    {
        m_VirgoAngle = degrees + 165;
        updatePulseProfile();
    
        updateGL();
    }
    
    void PulsarAnimationWidget::setSourceIota(const int degrees)
    {
        m_sourceIota = degrees;
        updatePulseProfile();
    
        updateGL();
    }
    
    void PulsarAnimationWidget::getCameraPosition(double& cameraAngleH, double& cameraAngleV, double& cameraZoom)
    {
        cameraAngleH = m_mouseAngleH;
        cameraAngleV = m_mouseAngleV;
        cameraZoom = m_cameraZoom;
    }
    
    void PulsarAnimationWidget::resetCameraPosition(const double angleH, const double angleV, const double zoom)
    {
        m_mouseAngleH = angleH;
        m_mouseAngleV = angleV;
        m_cameraZoom = zoom;
    
        updateCameraPosition(m_mouseAngleH, m_mouseAngleV, m_cameraZoom);
    }
    
    void PulsarAnimationWidget::updatePulseProfile()
    {
        for(int x = 0; x < 360; ++x) {
            m_pulseProfile[x] = 0;
        }
    
        // propagate new profile
        emit pulseProfileUpdated(m_pulseProfile);
    }