Q3DWidget.cc 17.7 KB
Newer Older
lm's avatar
lm committed
1 2 3
#include "Q3DWidget.h"

#include <cmath>
pixhawk's avatar
pixhawk committed
4 5 6

//#include <GL/gl.h>
//#include <GL/glu.h>
lm's avatar
lm committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

static const float KEY_ROTATE_AMOUNT = 5.0f;
static const float KEY_MOVE_AMOUNT   = 10.0f;
static const float KEY_ZOOM_AMOUNT   = 5.0f;

Q3DWidget::Q3DWidget(QWidget* parent)
  : QGLWidget(QGLFormat(QGL::Rgba | QGL::DoubleBuffer | QGL:: DepthBuffer |
                        QGL::StencilBuffer), parent)
  , userDisplayFunc(NULL)
  , userKeyboardFunc(NULL)
  , userMouseFunc(NULL)
  , userMotionFunc(NULL)
  , userDisplayFuncData(NULL)
  , userKeyboardFuncData(NULL)
  , userMouseFuncData(NULL)
  , userMotionFuncData(NULL)
  , windowWidth(0)
  , windowHeight(0)
  , requestedFps(0.0f)
  , lastMouseX(0)
  , lastMouseY(0)
  , _is3D(true)
  , _forceRedraw(false)
  , allow2DRotation(true)
  , limitCamera(false)
32
  , lockCamera(false)
lm's avatar
lm committed
33 34 35
  , timerFunc(NULL)
  , timerFuncData(NULL)
{
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
    cameraPose.state = IDLE;
    cameraPose.pan = 0.0f;
    cameraPose.tilt = 180.0f;
    cameraPose.distance = 10.0f;
    cameraPose.xOffset = 0.0f;
    cameraPose.yOffset = 0.0f;
    cameraPose.zOffset = 0.0f;

    cameraPose.xOffset2D = 0.0f;
    cameraPose.yOffset2D = 0.0f;
    cameraPose.rotation2D = 0.0f;
    cameraPose.zoom = 1.0f;
    cameraPose.warpX = 1.0f;
    cameraPose.warpY = 1.0f;

    cameraParams.zoomSensitivity = 0.05f;
    cameraParams.rotateSensitivity = 0.5f;
    cameraParams.moveSensitivity = 0.001f;
    cameraParams.minZoomRange = 0.5f;
    cameraParams.cameraFov = 30.0f;
    cameraParams.minClipRange = 1.0f;
    cameraParams.maxClipRange = 400.0f;
    cameraParams.zoomSensitivity2D = 0.02f;
    cameraParams.rotateSensitivity2D = 0.005f;
    cameraParams.moveSensitivity2D = 1.0f;
lm's avatar
lm committed
61 62 63 64 65 66 67 68 69 70 71
}

Q3DWidget::~Q3DWidget()
{

}

void
Q3DWidget::initialize(int32_t windowX, int32_t windowY,
                      int32_t windowWidth, int32_t windowHeight, float fps)
{
72 73
    this->windowWidth = windowWidth;
    this->windowHeight = windowHeight;
lm's avatar
lm committed
74

75
    requestedFps = fps;
lm's avatar
lm committed
76

77 78
    resize(windowWidth, windowHeight);
    move(windowX, windowY);
lm's avatar
lm committed
79

80
    timer.start(static_cast<int>(floorf(1000.0f / requestedFps)), this);
lm's avatar
lm committed
81

82
    _is3D = true;
lm's avatar
lm committed
83 84 85 86 87 88 89 90
}

void
Q3DWidget::setCameraParams(float zoomSensitivity, float rotateSensitivity,
							 float moveSensitivity, float minZoomRange,
							 float cameraFov, float minClipRange,
							 float maxClipRange)
{
91 92 93 94 95 96 97
    cameraParams.zoomSensitivity = zoomSensitivity;
    cameraParams.rotateSensitivity = rotateSensitivity;
    cameraParams.moveSensitivity = moveSensitivity;
    cameraParams.minZoomRange = minZoomRange;
    cameraParams.cameraFov = cameraFov;
    cameraParams.minClipRange = minClipRange;
    cameraParams.maxClipRange = maxClipRange;
lm's avatar
lm committed
98

99 100
    limitCamera = true;
    _forceRedraw = true;
lm's avatar
lm committed
101 102 103 104 105
}

void
Q3DWidget::setCameraLimit(bool onoff)
{
106 107 108 109 110 111 112
    limitCamera = onoff;
}

void
Q3DWidget::setCameraLock(bool onoff)
{
    lockCamera = onoff;
lm's avatar
lm committed
113 114 115 116 117 118 119
}

void
Q3DWidget::set2DCameraParams(float zoomSensitivity2D,
                             float rotateSensitivity2D,
                             float moveSensitivity2D)
{
120 121 122
    cameraParams.zoomSensitivity2D = zoomSensitivity2D;
    cameraParams.rotateSensitivity2D = rotateSensitivity2D;
    cameraParams.moveSensitivity2D = moveSensitivity2D;
lm's avatar
lm committed
123 124 125 126 127
}

void
Q3DWidget::set3D(bool onoff)
{
128
    _is3D = onoff;
lm's avatar
lm committed
129 130 131 132 133
}

bool
Q3DWidget::is3D(void) const
{
134
    return _is3D;
lm's avatar
lm committed
135 136 137 138 139 140
}

void
Q3DWidget::setInitialCameraPos(float pan, float tilt, float range,
								 float xOffset, float yOffset, float zOffset)
{
141 142 143 144 145 146
    cameraPose.pan = pan;
    cameraPose.tilt = tilt;
    cameraPose.distance = range;
    cameraPose.xOffset = xOffset;
    cameraPose.yOffset = yOffset;
    cameraPose.zOffset = zOffset;
lm's avatar
lm committed
147 148 149 150 151 152
}

void
Q3DWidget::setInitial2DCameraPos(float xOffset, float yOffset,
								   float rotation, float zoom)
{
153 154 155 156
    cameraPose.xOffset2D = xOffset;
    cameraPose.yOffset2D = yOffset;
    cameraPose.rotation2D = rotation;
    cameraPose.zoom = zoom;
lm's avatar
lm committed
157 158 159 160 161
}

void
Q3DWidget::setCameraPose(const CameraPose& cameraPose)
{
162
    this->cameraPose = cameraPose;
lm's avatar
lm committed
163 164 165 166 167
}

CameraPose
Q3DWidget::getCameraPose(void) const
{
168
    return cameraPose;
lm's avatar
lm committed
169 170 171 172 173
}

void
Q3DWidget::setDisplayFunc(DisplayFunc func, void* clientData)
{
174 175
    userDisplayFunc = func;
    userDisplayFuncData = clientData;
lm's avatar
lm committed
176 177 178 179 180
}

void
Q3DWidget::setKeyboardFunc(KeyboardFunc func, void* clientData)
{
181 182
    userKeyboardFunc = func;
    userKeyboardFuncData = clientData;
lm's avatar
lm committed
183 184 185 186 187
}

void
Q3DWidget::setMouseFunc(MouseFunc func, void* clientData)
{
188 189
    userMouseFunc = func;
    userMouseFuncData = clientData;
lm's avatar
lm committed
190 191 192 193 194
}

void
Q3DWidget::setMotionFunc(MotionFunc func, void* clientData)
{
195 196
    userMotionFunc = func;
    userMotionFuncData = clientData;
lm's avatar
lm committed
197 198 199 200 201 202
}

void
Q3DWidget::addTimerFunc(uint32_t msecs, void(*func)(void *),
                          void* clientData)
{
203 204
    timerFunc = func;
    timerFuncData = clientData;
lm's avatar
lm committed
205

206
    QTimer::singleShot(msecs, this, SLOT(userTimer()));
lm's avatar
lm committed
207 208 209 210 211
}

void
Q3DWidget::userTimer(void)
{
212 213 214 215
    if (timerFunc)
    {
            timerFunc(timerFuncData);
    }
lm's avatar
lm committed
216 217 218 219 220
}

void
Q3DWidget::forceRedraw(void)
{
221
    _forceRedraw = true;
lm's avatar
lm committed
222 223 224 225 226
}

void
Q3DWidget::set2DWarping(float warpX, float warpY)
{
227 228
    cameraPose.warpX = warpX;
    cameraPose.warpY = warpY;
lm's avatar
lm committed
229 230 231 232 233
}

void
Q3DWidget::recenter(void)
{
234 235 236
    cameraPose.xOffset = 0.0f;
    cameraPose.yOffset = 0.0f;
    cameraPose.zOffset = 0.0f;
lm's avatar
lm committed
237 238 239 240 241
}

void
Q3DWidget::recenter2D(void)
{
242 243
    cameraPose.xOffset2D = 0.0f;
    cameraPose.yOffset2D = 0.0f;
lm's avatar
lm committed
244 245 246 247 248
}

void
Q3DWidget::set2DRotation(bool onoff)
{
249
    allow2DRotation = onoff;
lm's avatar
lm committed
250 251
}

252 253 254
void
Q3DWidget::setDisplayMode2D(void)
{
255 256 257 258 259 260 261 262
    glDisable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, static_cast<GLfloat>(getWindowWidth()),
            0.0, static_cast<GLfloat>(getWindowHeight()),
            -10.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
263 264
}

lm's avatar
lm committed
265
std::pair<float,float>
266
Q3DWidget::getPositionIn3DMode(int32_t mouseX, int32_t mouseY)
lm's avatar
lm committed
267
{
268 269 270 271 272 273
    float cx = windowWidth / 2.0f;
    float cy = windowHeight / 2.0f;
    float pan = d2r(-90.0f - cameraPose.pan);
    float tilt = d2r(90.0f - cameraPose.tilt);
    float d = cameraPose.distance;
    float f = cy / tanf(d2r(cameraParams.cameraFov / 2.0f));
lm's avatar
lm committed
274

275 276 277 278
    float px = (mouseX - cx) * cosf(tilt) * d / (cosf(tilt) * f + sinf(tilt)
                            * mouseY - sinf(tilt) * cy);
    float py = -(mouseY - cy) * d / (cosf(tilt) * f + sinf(tilt) * mouseY
                            - sinf(tilt) * cy);
lm's avatar
lm committed
279

280 281 282
    std::pair<float,float> sceneCoords;
    sceneCoords.first = px * cosf(pan) + py * sinf(pan) + cameraPose.xOffset;
    sceneCoords.second = -px * sinf(pan) + py * cosf(pan) + cameraPose.yOffset;
lm's avatar
lm committed
283

284
    return sceneCoords;
lm's avatar
lm committed
285 286 287
}

std::pair<float,float>
288
Q3DWidget::getPositionIn2DMode(int32_t mouseX, int32_t mouseY)
lm's avatar
lm committed
289
{
290 291 292 293
    float dx = (mouseX - windowWidth / 2.0f) / cameraPose.zoom;
    float dy = (windowHeight / 2.0f - mouseY) / cameraPose.zoom;
    float ctheta = cosf(-cameraPose.rotation2D);
    float stheta = sinf(-cameraPose.rotation2D);
lm's avatar
lm committed
294

295 296 297
    std::pair<float,float> coords;
    coords.first = cameraPose.xOffset2D + ctheta * dx - stheta * dy;
    coords.second = cameraPose.yOffset2D + stheta * dx + ctheta * dy;
lm's avatar
lm committed
298

299
    return coords;
lm's avatar
lm committed
300 301 302 303 304
}

int
Q3DWidget::getWindowWidth(void)
{
305
    return windowWidth;
lm's avatar
lm committed
306 307 308 309 310
}

int
Q3DWidget::getWindowHeight(void)
{
311
    return windowHeight;
lm's avatar
lm committed
312 313 314 315 316
}

int
Q3DWidget::getLastMouseX(void)
{
317
    return lastMouseX;
lm's avatar
lm committed
318 319 320 321 322
}

int
Q3DWidget::getLastMouseY(void)
{
323
    return lastMouseY;
lm's avatar
lm committed
324 325 326 327 328
}

int
Q3DWidget::getMouseX(void)
{
329
    return mapFromGlobal(cursor().pos()).x();
lm's avatar
lm committed
330 331 332 333 334
}

int
Q3DWidget::getMouseY(void)
{
335
    return mapFromGlobal(cursor().pos()).y();
lm's avatar
lm committed
336 337 338 339 340 341
}


void
Q3DWidget::rotateCamera(float dx, float dy)
{
342 343
    if (!lockCamera)
    {
lm's avatar
lm committed
344 345 346 347
	cameraPose.pan += dx * cameraParams.rotateSensitivity;
	cameraPose.tilt += dy * cameraParams.rotateSensitivity;
	if (limitCamera)
	{
348 349 350 351 352 353 354 355
            if (cameraPose.tilt < 180.5f)
            {
                cameraPose.tilt = 180.5f;
            }
            else if (cameraPose.tilt > 269.5f)
            {
                cameraPose.tilt = 269.5f;
            }
lm's avatar
lm committed
356
	}
357
    }
lm's avatar
lm committed
358 359 360 361 362
}

void
Q3DWidget::zoomCamera(float dy)
{
363 364 365 366 367 368
    cameraPose.distance -=
            dy * cameraParams.zoomSensitivity * cameraPose.distance;
    if (cameraPose.distance < cameraParams.minZoomRange)
    {
        cameraPose.distance = cameraParams.minZoomRange;
    }
lm's avatar
lm committed
369 370 371 372 373
}

void
Q3DWidget::moveCamera(float dx, float dy)
{
374 375 376 377 378 379 380 381 382 383
    cameraPose.xOffset +=
            -dy * cosf(d2r(cameraPose.pan)) * cameraParams.moveSensitivity
            * cameraPose.distance;
    cameraPose.yOffset +=
            -dy * sinf(d2r(cameraPose.pan)) * cameraParams.moveSensitivity
            * cameraPose.distance;
    cameraPose.xOffset += dx * cosf(d2r(cameraPose.pan - 90.0f))
            * cameraParams.moveSensitivity * cameraPose.distance;
    cameraPose.yOffset += dx * sinf(d2r(cameraPose.pan - 90.0f))
            * cameraParams.moveSensitivity * cameraPose.distance;
lm's avatar
lm committed
384 385 386 387 388
}

void
Q3DWidget::rotateCamera2D(float dx)
{
389 390 391 392
    if (allow2DRotation)
    {
        cameraPose.rotation2D += dx * cameraParams.rotateSensitivity2D;
    }
lm's avatar
lm committed
393 394 395 396 397
}

void
Q3DWidget::zoomCamera2D(float dx)
{
398 399 400 401 402 403 404 405 406
    cameraPose.zoom += dx * cameraParams.zoomSensitivity2D * cameraPose.zoom;
    if (cameraPose.zoom > 1e7f)
    {
        cameraPose.zoom = 1e7f;
    }
    if (cameraPose.zoom < 1e-7f)
    {
        cameraPose.zoom = 1e-7f;
    }
lm's avatar
lm committed
407 408 409 410 411
}

void
Q3DWidget::moveCamera2D(float dx, float dy)
{
412 413
    float scaledX = dx / cameraPose.zoom;
    float scaledY = dy / cameraPose.zoom;
lm's avatar
lm committed
414

415 416 417 418 419 420
    cameraPose.xOffset2D -= (scaledX * cosf(-cameraPose.rotation2D)
            + scaledY * sinf(-cameraPose.rotation2D)) / cameraPose.warpX
            * cameraParams.moveSensitivity2D;
    cameraPose.yOffset2D -= (scaledX * sinf(-cameraPose.rotation2D)
            - scaledY * cosf(-cameraPose.rotation2D)) / cameraPose.warpY
            * cameraParams.moveSensitivity2D;
lm's avatar
lm committed
421 422 423 424
}

void Q3DWidget::switchTo3DMode(void)
{
425 426 427 428 429 430 431 432 433 434 435 436
    // setup camera view
    float cpan = d2r(cameraPose.pan);
    float ctilt = d2r(cameraPose.tilt);
    float cameraX = cameraPose.distance * cosf(cpan) * cosf(ctilt);
    float cameraY = cameraPose.distance * sinf(cpan) * cosf(ctilt);
    float cameraZ = cameraPose.distance * sinf(ctilt);
    setDisplayMode3D();
    glViewport(0, 0, static_cast<GLsizei>(windowWidth),
               static_cast<GLsizei>(windowHeight));
    gluLookAt(cameraX + cameraPose.xOffset, cameraY + cameraPose.yOffset,
              cameraZ + cameraPose.zOffset, cameraPose.xOffset,
              cameraPose.yOffset, cameraPose.zOffset, 0.0, 0.0, 1.0);
lm's avatar
lm committed
437 438 439
}

void
440
Q3DWidget::setDisplayMode3D()
lm's avatar
lm committed
441
{
442 443
    float aspect = static_cast<float>(getWindowWidth()) /
                   static_cast<float>(getWindowHeight());
lm's avatar
lm committed
444

445 446 447 448 449 450 451 452
    glEnable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(cameraParams.cameraFov, aspect,
                   cameraParams.minClipRange, cameraParams.maxClipRange);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glScalef(-1.0f, -1.0f, 1.0f);
lm's avatar
lm committed
453 454 455 456 457
}

float
Q3DWidget::r2d(float angle)
{
458
    return angle * 57.295779513082320876f;
lm's avatar
lm committed
459 460 461 462 463
}

float
Q3DWidget::d2r(float angle)
{
464
    return angle * 0.0174532925199432957692f;
lm's avatar
lm committed
465 466 467 468 469
}

void
Q3DWidget::initializeGL(void)
{
470 471 472 473
    float lightAmbient[] = {0.0f, 0.0f, 0.0f, 0.0f};
    float lightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
    float lightSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f};
    float lightPosition[] = {0.0f, 0.0f, 100.0f, 0.0f};
lm's avatar
lm committed
474

475 476 477 478 479 480 481 482 483
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
    glEnable(GL_LIGHT0);
    glDisable(GL_LIGHTING);
    glEnable(GL_NORMALIZE);
lm's avatar
lm committed
484 485 486 487 488
}

void
Q3DWidget::paintGL(void)
{
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
    if (_is3D)
    {
        // setup camera view
        switchTo3DMode();
    }
    else
    {
        setDisplayMode2D();
        // do camera control
        glTranslatef(static_cast<float>(windowWidth) / 2.0f,
                                 static_cast<float>(windowHeight) / 2.0f,
                                 0.0f);
        glScalef(cameraPose.zoom, cameraPose.zoom, 1.0f);
        glRotatef(r2d(cameraPose.rotation2D), 0.0f, 0.0f, 1.0f);
        glScalef(cameraPose.warpX, cameraPose.warpY, 1.0f);
        glTranslatef(-cameraPose.xOffset2D, -cameraPose.yOffset2D, 0.0f);
    }

    // turn on smooth lines
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_LINE_SMOOTH);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLineWidth(1.0f);

    if (userDisplayFunc)
    {
        userDisplayFunc(userDisplayFuncData);
    }
    glFlush();
lm's avatar
lm committed
521 522 523 524 525
}

void
Q3DWidget::resizeGL(int32_t width, int32_t height)
{
526
    glViewport(0, 0, width, height);
lm's avatar
lm committed
527

528 529
    windowWidth = width;
    windowHeight = height;
lm's avatar
lm committed
530

531 532 533 534 535 536 537 538
    if (_is3D)
    {
        setDisplayMode3D();
    }
    else
    {
        setDisplayMode2D();
    }
lm's avatar
lm committed
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
}

void
Q3DWidget::keyPressEvent(QKeyEvent* event)
{
	float dx = 0.0f, dy = 0.0f;

	Qt::KeyboardModifiers modifiers = event->modifiers();
	if (_is3D)
	{
		if (modifiers & Qt::ControlModifier)
		{
			switch (event->key())
			{
			case Qt::Key_Left:
				dx = -KEY_ROTATE_AMOUNT;
				dy = 0.0f;
				break;
			case Qt::Key_Right:
				dx = KEY_ROTATE_AMOUNT;
				dy = 0.0f;
				break;
			case Qt::Key_Up:
				dx = 0.0f;
				dy = KEY_ROTATE_AMOUNT;
				break;
			case Qt::Key_Down:
				dx = 0.0f;
				dy = -KEY_ROTATE_AMOUNT;
				break;
			default:
				QWidget::keyPressEvent(event);
			}
			if (dx != 0.0f || dy != 0.0f)
			{
				rotateCamera(dx, dy);
			}
		}
		else if (modifiers & Qt::AltModifier)
		{
			switch (event->key())
			{
			case Qt::Key_Up:
				dy = KEY_ZOOM_AMOUNT;
				break;
			case Qt::Key_Down:
				dy = -KEY_ZOOM_AMOUNT;
				break;
			default:
				QWidget::keyPressEvent(event);
			}
			if (dy != 0.0f)
			{
				zoomCamera(dy);
			}
		}
		else
		{
			switch (event->key())
			{
			case Qt::Key_Left:
				dx = KEY_MOVE_AMOUNT;
				dy = 0.0f;
				break;
			case Qt::Key_Right:
				dx = -KEY_MOVE_AMOUNT;
				dy = 0.0f;
				break;
			case Qt::Key_Up:
				dx = 0.0f;
				dy = -KEY_MOVE_AMOUNT;
				break;
			case Qt::Key_Down:
				dx = 0.0f;
				dy = KEY_MOVE_AMOUNT;
				break;
			default:
				QWidget::keyPressEvent(event);
			}
			if (dx != 0.0f || dy != 0.0f)
			{
				moveCamera(dx, dy);
			}
		}
	}
	else {
		if (modifiers & Qt::ControlModifier)
		{
			switch (event->key())
			{
			case Qt::Key_Left:
				dx = KEY_ROTATE_AMOUNT;
				dy = 0.0f;
				break;
			case Qt::Key_Right:
				dx = -KEY_ROTATE_AMOUNT;
				dy = 0.0f;
				break;
			default:
				QWidget::keyPressEvent(event);
			}
			if (dx != 0.0f)
			{
				rotateCamera2D(dx);
			}
		}
		else if (modifiers & Qt::AltModifier)
		{
			switch (event->key())
			{
			case Qt::Key_Up:
				dy = KEY_ZOOM_AMOUNT;
				break;
			case Qt::Key_Down:
				dy = -KEY_ZOOM_AMOUNT;
				break;
			default:
				QWidget::keyPressEvent(event);
			}
			if (dy != 0.0f)
			{
				zoomCamera2D(dy);
			}
		}
		else {
			switch (event->key())
			{
			case Qt::Key_Left:
				dx = KEY_MOVE_AMOUNT;
				dy = 0.0f;
				break;
			case Qt::Key_Right:
				dx = -KEY_MOVE_AMOUNT;
				dy = 0.0f;
				break;
			case Qt::Key_Up:
				dx = 0.0f;
				dy = KEY_MOVE_AMOUNT;
				break;
			case Qt::Key_Down:
				dx = 0.0f;
				dy = -KEY_MOVE_AMOUNT;
				break;
			default:
				QWidget::keyPressEvent(event);
			}
			if (dx != 0.0f || dy != 0.0f)
			{
				moveCamera2D(dx, dy);
			}
		}
	}

	_forceRedraw = true;

	if (userKeyboardFunc)
	{
		if (event->text().isEmpty())
		{
			userKeyboardFunc(0, userKeyboardFuncData);
		}
		else
		{
			userKeyboardFunc(event->text().at(0).toAscii(),
							 userKeyboardFuncData);
		}
	}
}

void
Q3DWidget::mousePressEvent(QMouseEvent* event)
{
	Qt::KeyboardModifiers modifiers = event->modifiers();

	if (!(modifiers & (Qt::ControlModifier | Qt::AltModifier)))
	{
		lastMouseX = event->x();
		lastMouseY = event->y();
		if (event->button() == Qt::LeftButton)
		{
			cameraPose.state = ROTATING;
		}
		else if (event->button() == Qt::MidButton)
		{
			cameraPose.state = MOVING;
		}
		else if (event->button() == Qt::RightButton)
		{
			cameraPose.state = ZOOMING;
		}
	}

	_forceRedraw = true;

	if (userMouseFunc)
	{
		userMouseFunc(event->button(), MOUSE_STATE_DOWN, event->x(), event->y(),
					  userMouseFuncData);
	}
}

void
Q3DWidget::mouseReleaseEvent(QMouseEvent* event)
{
	Qt::KeyboardModifiers modifiers = event->modifiers();

	if (!(modifiers & (Qt::ControlModifier | Qt::AltModifier)))
	{
		cameraPose.state = IDLE;
	}

	_forceRedraw = true;

	if (userMouseFunc)
	{
		userMouseFunc(event->button(), MOUSE_STATE_UP, event->x(), event->y(),
					  userMouseFuncData);
	}
}

void
Q3DWidget::mouseMoveEvent(QMouseEvent* event)
{
	int32_t dx = event->x() - lastMouseX;
	int32_t dy = event->y() - lastMouseY;

	if (_is3D)
	{
		if (cameraPose.state == ROTATING)
		{
			rotateCamera(static_cast<float>(dx), static_cast<float>(dy));
		}
		else if (cameraPose.state == MOVING)
		{
			moveCamera(static_cast<float>(dx), static_cast<float>(dy));
		}
		else if (cameraPose.state == ZOOMING)
		{
			zoomCamera(static_cast<float>(dy));
		}
	}
	else
	{
		if (cameraPose.state == ROTATING)
		{
			if (event->x() > windowWidth / 2)
			{
				dy *= -1;
			}

			rotateCamera2D(static_cast<float>(dx));
		}
		else if (cameraPose.state == MOVING)
		{
			moveCamera2D(static_cast<float>(dx), static_cast<float>(dy));
		}
		else if (cameraPose.state == ZOOMING)
		{
			zoomCamera2D(static_cast<float>(dy));
		}
	}

	lastMouseX = event->x();
	lastMouseY = event->y();
	_forceRedraw = true;

	if (userMotionFunc)
	{
		userMotionFunc(event->x(), event->y(), userMotionFuncData);
	}
}

void
Q3DWidget::wheelEvent(QWheelEvent* event)
{
	if (_is3D)
	{
		zoomCamera(static_cast<float>(event->delta()) / 40.0f);
	}
	else
	{
		zoomCamera2D(static_cast<float>(event->delta()) / 40.0f);
	}

	_forceRedraw = true;
}

void
Q3DWidget::timerEvent(QTimerEvent* event)
{
	if (event->timerId() == timer.timerId())
	{
		if (_forceRedraw)
		{
			updateGL();
			_forceRedraw = false;
		}
	}
	else
	{
		QObject::timerEvent(event);
	}
}

void
Q3DWidget::closeEvent(QCloseEvent *)
{
846
    // exit application
lm's avatar
lm committed
847
}