pulsaranimationwidget.cpp 21.1 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
/******************************************************************************
 *   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"
22
#include "lib/antenna_lib.h"
Oliver Bock's avatar
Oliver Bock committed
23

Oliver Bock's avatar
Oliver Bock committed
24
const double PulsarAnimationWidget::deg2rad = PI/180.0;
25

Oliver Bock's avatar
Oliver Bock committed
26
PulsarAnimationWidget::PulsarAnimationWidget(QWidget *parent) :
27
    QGLWidget(QGLFormat(QGL::AlphaChannel | QGL::SampleBuffers), parent)
Oliver Bock's avatar
Oliver Bock committed
28
{
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    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);
    }

Oliver Bock's avatar
Oliver Bock committed
51
    // initialize quadric pointers
Oliver Bock's avatar
Oliver Bock committed
52
53
    m_quadricVirgoh = NULL;
    m_quadricVirgov = NULL;
Oliver Bock's avatar
Oliver Bock committed
54
    m_quadricEarth = NULL;
Oliver Bock's avatar
Oliver Bock committed
55
56
    m_quadricLLOh = NULL;
    m_quadricLLOv = NULL;
Oliver Bock's avatar
Oliver Bock committed
57
58
59
    m_quadricSourcePlane = NULL;
    m_quadricSourcePlaneNormal = NULL;
    m_quadricSourcePlaneNormalCap = NULL;
60
    m_quadricSourcePlaneNormalCenter = NULL;
61
62
    m_quadricLHOv = NULL;
    m_quadricLHOh = NULL;
63
64

    // initialize texture pointers
65
    m_beamTexture = 0;
66

67
    // initial parameters (have to match GUI!)
68
69
70
    m_LHOAngle = 0;
    m_LLOAngle = 0;
    m_VirgoAngle = 0;
Oliver Bock's avatar
Oliver Bock committed
71
    m_sourceIota = 0.0;
72
    m_sourceInclination = 0;
73

Oliver Bock's avatar
Oliver Bock committed
74
    m_earthRadius = 3.0;
75

76
77
78
79
    // initial view features
    m_cameraInteraction = false;

    // initial view settings
80
81
    m_mouseAngleH = -55.0;
    m_mouseAngleV = 20.0;
82
    m_cameraZoom = 100.0;
83
84
85
86
87
88
89
    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);
Oliver Bock's avatar
Oliver Bock committed
90
91
92
93
}

PulsarAnimationWidget::~PulsarAnimationWidget()
{
Oliver Bock's avatar
Oliver Bock committed
94
95
    if(m_quadricVirgoh) gluDeleteQuadric(m_quadricVirgoh);
    if(m_quadricVirgov) gluDeleteQuadric(m_quadricVirgov);
Oliver Bock's avatar
Oliver Bock committed
96
    if(m_quadricEarth) gluDeleteQuadric(m_quadricEarth);
Oliver Bock's avatar
Oliver Bock committed
97
98
    if(m_quadricLLOh) gluDeleteQuadric(m_quadricLLOh);
    if(m_quadricLLOv) gluDeleteQuadric(m_quadricLLOv);
Oliver Bock's avatar
Oliver Bock committed
99
100
101
    if(m_quadricSourcePlane) gluDeleteQuadric(m_quadricSourcePlane);
    if(m_quadricSourcePlaneNormal) gluDeleteQuadric(m_quadricSourcePlaneNormal);
    if(m_quadricSourcePlaneNormalCap) gluDeleteQuadric(m_quadricSourcePlaneNormalCap);
102
    if(m_quadricSourcePlaneNormalCenter) gluDeleteQuadric(m_quadricSourcePlaneNormalCenter);
103
104
    if(m_quadricLHOv) gluDeleteQuadric(m_quadricLHOv);
    if(m_quadricLHOh) gluDeleteQuadric(m_quadricLHOh);
Oliver Bock's avatar
Oliver Bock committed
105
106
107
108
}

void PulsarAnimationWidget::initializeGL()
{
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
    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);

Oliver Bock's avatar
Oliver Bock committed
137
138
    m_quadricVirgoh = gluNewQuadric();
    m_quadricVirgov = gluNewQuadric();
Oliver Bock's avatar
Oliver Bock committed
139
    m_quadricEarth = gluNewQuadric();
Oliver Bock's avatar
Oliver Bock committed
140
141
    m_quadricLLOh = gluNewQuadric();
    m_quadricLLOv = gluNewQuadric();
Oliver Bock's avatar
Oliver Bock committed
142
143
144
    m_quadricSourcePlane = gluNewQuadric();
    m_quadricSourcePlaneNormal = gluNewQuadric();
    m_quadricSourcePlaneNormalCap = gluNewQuadric();
145
    m_quadricSourcePlaneNormalCenter = gluNewQuadric();
146
147
    m_quadricLHOv = gluNewQuadric();
    m_quadricLHOh = gluNewQuadric();
148

Oliver Bock's avatar
Oliver Bock committed
149
150
    gluQuadricNormals(m_quadricVirgoh, GLU_SMOOTH);
    gluQuadricNormals(m_quadricVirgov, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
151
    gluQuadricNormals(m_quadricEarth, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
152
153
    gluQuadricNormals(m_quadricLLOh, GLU_SMOOTH);
    gluQuadricNormals(m_quadricLLOv, GLU_SMOOTH);
Oliver Bock's avatar
Oliver Bock committed
154
155
156
    gluQuadricNormals(m_quadricSourcePlane, GLU_SMOOTH);
    gluQuadricNormals(m_quadricSourcePlaneNormal, GLU_SMOOTH);
    gluQuadricNormals(m_quadricSourcePlaneNormalCap, GLU_SMOOTH);
157
    gluQuadricNormals(m_quadricSourcePlaneNormalCenter, GLU_SMOOTH);
158
159
    gluQuadricNormals(m_quadricLHOv, GLU_SMOOTH);
    gluQuadricNormals(m_quadricLHOh, GLU_SMOOTH);
160

Oliver Bock's avatar
Oliver Bock committed
161
162
163
164
    // query max texture size (estimate)
    GLint maxTextureSize;
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);

165
    // prepare and check beam texture
166
    QImage beamTexture(":/textures/resources/World-Map-7.jpg");
167

Oliver Bock's avatar
Oliver Bock committed
168
    // bind textures
169
    m_beamTexture = bindTexture(beamTexture, GL_TEXTURE_2D, GL_RGBA);
170

171
    // use mipmapped textures
172
173
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
Oliver Bock's avatar
Oliver Bock committed
174
175
176
177
}

void PulsarAnimationWidget::resizeGL(int w, int h)
{
178
    glViewport(0, 0, w, h);
Oliver Bock's avatar
Oliver Bock committed
179

180
181
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
Oliver Bock's avatar
Oliver Bock committed
182

183
    gluPerspective(4.5, (GLfloat)w / (GLfloat)h, 0.1, 5000.0);
Oliver Bock's avatar
Oliver Bock committed
184

185
186
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
Oliver Bock's avatar
Oliver Bock committed
187
188
189
190
}

void PulsarAnimationWidget::paintGL()
{
191
192
    GLfloat x,y,angle;

193
194
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

195
196
    // TODO: should be located elsewhere
    static GLfloat no_mat[] = {0.0, 0.0, 0.0, 1.0};
197
    static GLfloat mat_diffuse[] = {0.0, 0.0, 0.5, 1.0};
198
199
200
201
202
203
204
205
206
207
    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);

208
209
210
211
212
213
214
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    gluLookAt(m_cameraPosX, m_cameraPosY, m_cameraPosZ,
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);

215
216
217
218
219
220
221
222
223
224
225
226
    // 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)
227
            glColor3f(1.0, 1.0, 1.0f);
228
229
230
231
232
233
234
235
236
237
            glTranslatef(0.0, 0.0, -501.0);

            // restore original state
            glMatrixMode(GL_PROJECTION);
        }
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
    }
    glPopMatrix();

Oliver Bock's avatar
Oliver Bock committed
238
    // draw earth
239
    glPushMatrix();
240
    {
241
        glRotatef(90, 0.0, 1.0, 0.0);
242
        glPushMatrix();
243
244
        {
            glRotatef(90, 1.0, 0.0, 0.0);
245
246
            glRotatef(180, 1.0, 1.0, 0.0);

247
248
249
250
            glDisable(GL_DEPTH_TEST);
            glEnable(GL_CULL_FACE);
            glColor4f(1.0, 1.0, 1.0f, 0.8f);

251
            // create texture coordinates and enable texturing
Oliver Bock's avatar
Oliver Bock committed
252
            gluQuadricTexture(m_quadricEarth, GL_TRUE);
253
254
            glBindTexture(GL_TEXTURE_2D, m_beamTexture);
            glEnable(GL_TEXTURE_2D);
255

256
257
258
            glCullFace(GL_FRONT);
            gluSphere(m_quadricEarth, m_earthRadius, 32, 32);
            glCullFace(GL_BACK);
Oliver Bock's avatar
Oliver Bock committed
259
            gluSphere(m_quadricEarth, m_earthRadius, 32, 32);
260
261
262

            glDisable(GL_CULL_FACE);
            glEnable(GL_DEPTH_TEST);
263
264
        }
        glPopMatrix();
265
266
    }
    glPopMatrix();
267

268
269
270
271
272
    // draw LHO
    glPushMatrix();
    {
        glColor3f(1.0f, 1.0f, 1.0f);

273
274
275
        glRotatef(-48.455144, 0.0, 0.0, 1.0);
        glRotatef(-110.407656, 0.0, 1.0, 0.0);

Oliver Bock's avatar
Oliver Bock committed
276
        glTranslatef(0.0, 0.0, m_earthRadius);
277

278
        glRotatef(m_LHOAngle+180, 0.0, 0.0, 1.0);
279
280
281
        glPushMatrix();
        {
            glRotatef(90, 0.0, 1.0, 0.0);
282
            gluCylinder(m_quadricLHOh, 0.020, 0.020, 0.40, 32, 1);
283
284
285
286
287
288
289
        }
        glPopMatrix();

        glPushMatrix();
        {
            glRotatef(90, 0.0, 1.0, 0.0);
            glRotatef(90, 1.0, 0.0, 0.0);
290
291
            glColor3f(0.0f, 0.0f, 1.0f);
            gluCylinder(m_quadricLHOv, 0.020, 0.020, 0.40, 32, 1);
292
293
294
295
296
        }
        glPopMatrix();
    }
    glPopMatrix();

Oliver Bock's avatar
Oliver Bock committed
297
298
299
300
301
    // draw LLO
    glPushMatrix();
    {
        glColor3f(1.0f, 1.0f, 1.0f);

302
303
304
        glRotatef(-30.562894, 0.0, 0.0, 1.0);
        glRotatef(-90.774242, 0.0, 1.0, 0.0);

Oliver Bock's avatar
Oliver Bock committed
305
        glTranslatef(0.0, 0.0, m_earthRadius);
306

307
        glRotatef(m_LLOAngle-90, 0.0, 0.0, 1.0);
Oliver Bock's avatar
Oliver Bock committed
308
309
310
        glPushMatrix();
        {
            glRotatef(90, 0.0, 1.0, 0.0);
311
            gluCylinder(m_quadricLLOh, 0.020, 0.020, 0.40, 32, 1);
Oliver Bock's avatar
Oliver Bock committed
312
313
314
315
316
317
318
        }
        glPopMatrix();

        glPushMatrix();
        {
            glRotatef(90, 0.0, 1.0, 0.0);
            glRotatef(90, 1.0, 0.0, 0.0);
319
320
            glColor3f(1.0f, 0.0f, 0.0f);
            gluCylinder(m_quadricLLOv, 0.020, 0.020, 0.40, 32, 1);
Oliver Bock's avatar
Oliver Bock committed
321
322
323
324
325
        }
        glPopMatrix();
    }
    glPopMatrix();

Oliver Bock's avatar
Oliver Bock committed
326
327
328
329
330
    // draw Virgo
    glPushMatrix();
    {
        glColor3f(1.0f, 1.0f, 1.0f);

331
332
333
        glRotatef(-45.6305, 1.0, 0.0, 0.0);
        glRotatef(7.5021, 0.0, 1.0, 0.0);

Oliver Bock's avatar
Oliver Bock committed
334
        glTranslatef(0.0, 0.0, m_earthRadius);
335

336
        glRotatef(m_VirgoAngle+165, 0.0, 0.0, 1.0);
Oliver Bock's avatar
Oliver Bock committed
337
338
339
        glPushMatrix();
        {
            glRotatef(90, 0.0, 1.0, 0.0);
340
            gluCylinder(m_quadricVirgoh, 0.020, 0.020, 0.40, 32, 1);
Oliver Bock's avatar
Oliver Bock committed
341
342
343
344
345
346
347
        }
        glPopMatrix();

        glPushMatrix();
        {
            glRotatef(90, 0.0, 1.0, 0.0);
            glRotatef(90, 1.0, 0.0, 0.0);
348
349
            glColor3f(0.0f, 1.0f, 0.0f);
            gluCylinder(m_quadricVirgov, 0.020, 0.020, 0.40, 32, 1);
Oliver Bock's avatar
Oliver Bock committed
350
351
352
353
354
        }
        glPopMatrix();
    }
    glPopMatrix();

355
    // draw source
356
    glPushMatrix();
357
    {
358
359
360
361
        // The second rotation isn't right:
        // -> should be around x-axis (not z) and not mess up source iota from below!
        // -> does the x-axis not rotate with its object (around the first y-rotation)?
        // -> putting them in their own matrix doesn't help either
362
363
        glRotatef(-31.384, 0.0, 0.0, 1.0);
        glRotatef(45.093, 0.0, 1.0, 0.0);
364

Oliver Bock's avatar
Oliver Bock committed
365
        glTranslatef(0.0, 0.0, m_earthRadius + 2.0);
366

367
        glPushMatrix();
368
        {
369
            glRotatef(-m_sourceInclination+23.5, 0.0, 0.0, 1.0);
370
            glRotatef(180, 0.0, 1.0, 0.0);
Oliver Bock's avatar
Oliver Bock committed
371
            glRotatef(m_sourceIota, 0.0, 1.0, 0.0);
372

Oliver Bock's avatar
Oliver Bock committed
373
374
375
376
            // draw source plane normal
            glColor3f(1.0f, 0.0f, 0.0f);
            glPushMatrix();
            {
377
                glTranslatef(0.0, 0.0, -1.0);
Oliver Bock's avatar
Oliver Bock committed
378
                gluCylinder(m_quadricSourcePlaneNormal, 0.020, 0.020, 1.5, 32, 1);
Oliver Bock's avatar
Oliver Bock committed
379
380
381
382
            }
            glPopMatrix();
            glPushMatrix();
            {
383
                glTranslatef(0.0, 0.0, -1.0);
Oliver Bock's avatar
Oliver Bock committed
384
                gluDisk(m_quadricSourcePlaneNormalCap, 0, 0.020, 32, 8);
Oliver Bock's avatar
Oliver Bock committed
385
386
387
388
            }
            glPopMatrix();
            glPushMatrix();
            {
389
                glTranslatef(0.0, 0.0, 0.5f);
Oliver Bock's avatar
Oliver Bock committed
390
                glBegin(GL_TRIANGLE_FAN);
Oliver Bock's avatar
Oliver Bock committed
391
                {
Oliver Bock's avatar
Oliver Bock committed
392
393
                    // Pinnacle of cone is shared vertex for fan, moved up z-axis
                    // to produce a cone instead of a circle
394
                    glVertex3f(0.0f, 0.0f, 0.5f);
Oliver Bock's avatar
Oliver Bock committed
395
396
397
398

                    // 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))
Oliver Bock's avatar
Oliver Bock committed
399
                    {
Oliver Bock's avatar
Oliver Bock committed
400
                        // Calculate x and y position of the next vertex
401
402
                        x = 0.1f * sin(angle);
                        y = 0.1f * cos(angle);
Oliver Bock's avatar
Oliver Bock committed
403
404
405

                        // Specify the next vertex for the triangle fan
                        glVertex2f(x, y);
Oliver Bock's avatar
Oliver Bock committed
406
407
                    }
                }
Oliver Bock's avatar
Oliver Bock committed
408
                glEnd();
409
            }
Oliver Bock's avatar
Oliver Bock committed
410
            glPopMatrix();
411
412
413
414
415
416
            glColor3f(1.0f, 1.0f, 1.0f);
            glPushMatrix();
            {
                gluSphere(m_quadricSourcePlaneNormalCenter, 0.040, 32, 32);
            }
            glPopMatrix();
417

418
419
            // draw disc
            glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, translucent);
420
421
            glEnable(GL_LIGHTING);

422
            glPushMatrix();
423
            {
Oliver Bock's avatar
Oliver Bock committed
424
                gluDisk(m_quadricSourcePlane,
425
                        0,
426
                        1.0,
427
                        64, 1);
428
429
430
            }
            glPopMatrix();

431
            glDisable(GL_LIGHTING);
432
        }
433
434
        glPopMatrix();
    }
435
    glPopMatrix();
Oliver Bock's avatar
Oliver Bock committed
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

    // 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;
451
            font.setPointSize(14);
Oliver Bock's avatar
Oliver Bock committed
452
453
454
            font.setBold(true);
            font.setFamily("Arial");
            font.setStyleStrategy((QFont::StyleStrategy) (QFont::OpenGLCompatible | QFont::PreferQuality));
455
            renderText(10, 40, -100, tr("B. Allen and O. Bock"), font);
456
457
            renderText(10, 25, -100, tr("MPI for Gravitational Physics"));
            renderText(10, 10, -100, QString("Copyright %1 2017").arg(QChar(0x00A9)));
458
	    
Oliver Bock's avatar
Oliver Bock committed
459
460
461
462
463
464
465
            // restore original state
            glMatrixMode(GL_PROJECTION);
        }
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
    }
    glPopMatrix();
Oliver Bock's avatar
Oliver Bock committed
466
467
}

468
469
void PulsarAnimationWidget::mousePressEvent(QMouseEvent *event)
{
470
    Q_UNUSED(event);
471

472
473
    m_cameraInteraction = true;
    updateGL();
474
475
}

476
477
void PulsarAnimationWidget::mouseMoveEvent(QMouseEvent *event)
{
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
    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);
505
506
507
508
}

void PulsarAnimationWidget::mouseReleaseEvent(QMouseEvent *event)
{
509
    Q_UNUSED(event);
510

511
512
513
    m_mouseLastX = 0;
    m_mouseLastY = 0;
    m_cameraInteraction = false;
514

515
    updateGL();
516
517
}

Oliver Bock's avatar
Oliver Bock committed
518
519
void PulsarAnimationWidget::showEvent(QShowEvent *event)
{
520
    Q_UNUSED(event);
Oliver Bock's avatar
Oliver Bock committed
521

522
523
    // update and propagate pulse profile
    updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
524
525
}

Oliver Bock's avatar
Oliver Bock committed
526
void PulsarAnimationWidget::updateCameraPosition(const double angleH, const double angleV, const double zoom)
527
{
528
529
530
    m_cameraPosX = sin(angleH * deg2rad) * cos(angleV * deg2rad) * zoom;
    m_cameraPosY = sin(angleV * deg2rad) * zoom;
    m_cameraPosZ = cos(angleH * deg2rad) * cos(angleV * deg2rad) * zoom;
531

532
    updateGL();
533
534
}

535
void PulsarAnimationWidget::setSourceInclination(const double degrees)
Oliver Bock's avatar
Oliver Bock committed
536
{
537
538
539
540
541
542
543
544

   // This sign convention differs from my notes.  In my notes,
   // increasing psi means that the orbital ellipse rotates CCW when
   // viewed from above.  But the convention in LAL is that increasing
   // psi rotates the ellipse CCW when viewed from Earth, and CW when
   // viewed from above.  So I have adjusted this code to be
   // consistent with LAL, and inserted a factor of -1 in my code.
   // Bruce
545
    m_sourceInclination = degrees;
546
    updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
547

548
    updateGL();
Oliver Bock's avatar
Oliver Bock committed
549
}
550

Oliver Bock's avatar
Oliver Bock committed
551
void PulsarAnimationWidget::setLHOAngle(const double degrees)
552
{
553
    m_LHOAngle = degrees;
554
    updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
555

556
    updateGL();
557
558
}

559
void PulsarAnimationWidget::setLLOAngle(const double degrees)
560
{
561
    m_LLOAngle = degrees;
562
    updatePulseProfile();
Oliver Bock's avatar
Oliver Bock committed
563
564

    updateGL();
Oliver Bock's avatar
Oliver Bock committed
565
566
}

567
void PulsarAnimationWidget::setVirgoAngle(const int degrees)
Oliver Bock's avatar
Oliver Bock committed
568
{
569
    m_VirgoAngle = degrees;
570
    updatePulseProfile();
571

572
    updateGL();
573
574
}

Oliver Bock's avatar
Oliver Bock committed
575
void PulsarAnimationWidget::setSourceIota(const int degrees)
576
{
Oliver Bock's avatar
Oliver Bock committed
577
    m_sourceIota = degrees;
578
    updatePulseProfile();
579

580
    updateGL();
581
}
582

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
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);
}

599
600
void PulsarAnimationWidget::updatePulseProfile()
{
601
602
603
604
    struct InputStruct in;
    struct OutputStruct out;

    in.iota = m_sourceIota;
605
606
607
608
609
610
611
612

    // This sign convention for in.psi differs from my notes.  In my
    // notes, increasing psi means that the orbital ellipse rotates
    // CCW when viewed from above.  But the convention in LAL is that
    // increasing psi rotates the ellipse CCW when viewed from Earth,
    // and CW when viewed from above.  So I have adjusted this code to
    // be consistent with LAL, and inserted a factor of -1 in my code.
    // Bruce
613
614
615
616
617
    in.psi = m_sourceInclination;
    in.orientation[0] = m_LLOAngle;
    in.orientation[1] = m_LHOAngle;
    in.orientation[2] = m_VirgoAngle;

Oliver Bock's avatar
Oliver Bock committed
618
    // get actual detector data
619
620
    get_antenna(&out, &in);

Oliver Bock's avatar
Oliver Bock committed
621
    // populate plot data object
622
623
624
625
626
627
628
629
630
631
    
    // suppose that the initial frequency is 30 Hz and dx is the
    // amount of x range in one cycle.  That means that dx freq0= 360
    // => dx = 360/freq0 = 30ms.  Hence freq0 = 360/30ms.  The phase
    // delay in degrees caused by the offset in arrival time will then
    // be phase_delay_degrees = freq0 * out.dt = 360*out.dt/30ms.  The
    // x delay is then freq0*dx=360*out.dt/30ms => dx =
    // 360*out.dt/(freq0*30ms).

    double freq0 = 1.0/pow(1.1,0.375);
632
633
    double dx[3];
    
Bruce Allen's avatar
Bruce Allen committed
634
    for (int i=0; i<3; i++) dx[i]=360*out.dt[i]/(30.0*freq0);
635
    
636
    for(int x = 0; x < 360*PERIODS; ++x) {
637
638
       double t=x/(PERIODS*360.0);
       double freq = 1.0/pow(1.1-t,0.375);
Bruce Allen's avatar
Bruce Allen committed
639
640
641
       m_plotData.m_dataLLO[x]   = 0.8 * out.amp[0] * freq * freq * sin((freq*(x + dx[0]) + out.phase[0]) * deg2rad);
       m_plotData.m_dataLHO[x]   = 0.8 * out.amp[1] * freq * freq * sin((freq*(x + dx[1]) + out.phase[1]) * deg2rad);
       m_plotData.m_dataVirgo[x] = 0.8 * out.amp[2] * freq * freq * sin((freq*(x + dx[2]) + out.phase[2]) * deg2rad);
642
643
    }

Oliver Bock's avatar
Oliver Bock committed
644
645
646
647
648
649
650
651
652
653
654
655
656
    m_plotData.m_ampLLO   = out.amp[0];
    m_plotData.m_ampLHO   = out.amp[1];
    m_plotData.m_ampVirgo = out.amp[2];

    m_plotData.m_phiLLO   = out.phase[0];
    m_plotData.m_phiLHO   = out.phase[1];
    m_plotData.m_phiVirgo = out.phase[2];

    m_plotData.m_dtLLO   = out.dt[0];
    m_plotData.m_dtLHO   = out.dt[1];
    m_plotData.m_dtVirgo = out.dt[2];

    // propagate new plot data
657
    emit pulseProfileUpdated(m_plotData);
658
}