src/glRenderer.cpp

changeset 1013
fa025ba493d8
parent 1012
413ecd6b9801
child 1014
f0a8ecb6a357
equal deleted inserted replaced
1012:413ecd6b9801 1013:fa025ba493d8
539 if (camera() == EFreeCamera) 539 if (camera() == EFreeCamera)
540 return Origin; 540 return Origin;
541 541
542 Vertex pos3d; 542 Vertex pos3d;
543 const LDFixedCamera* cam = &g_FixedCameras[camera()]; 543 const LDFixedCamera* cam = &g_FixedCameras[camera()];
544 const Axis axisX = cam->localX; 544 Axis axisX = cam->localX;
545 const Axis axisY = cam->localY; 545 Axis axisY = cam->localY;
546 const int negXFac = cam->negatedX ? -1 : 1, 546 int signX = cam->negatedX ? -1 : 1;
547 negYFac = cam->negatedY ? -1 : 1; 547 int signY = cam->negatedY ? -1 : 1;
548 548
549 // Calculate cx and cy - these are the LDraw unit coords the cursor is at. 549 // Calculate cx and cy - these are the LDraw unit coords the cursor is at.
550 double cx = (-m_virtualWidth + ((2 * pos2d.x() * m_virtualWidth) / m_width) - panning (X)); 550 double cx = (-m_virtualWidth + ((2 * pos2d.x() * m_virtualWidth) / m_width) - panning (X));
551 double cy = (m_virtualHeight - ((2 * pos2d.y() * m_virtualHeight) / m_height) - panning (Y)); 551 double cy = (m_virtualHeight - ((2 * pos2d.y() * m_virtualHeight) / m_height) - panning (Y));
552 552
553 if (snap) 553 if (snap)
554 { 554 {
555 cx = Grid::Snap (cx, Grid::Coordinate); 555 cx = snapToGrid (cx, Grid::Coordinate);
556 cy = Grid::Snap (cy, Grid::Coordinate); 556 cy = snapToGrid (cy, Grid::Coordinate);
557 } 557 }
558 558
559 cx *= negXFac; 559 cx *= signX;
560 cy *= negYFac; 560 cy *= signY;
561 561
562 RoundToDecimals (cx, 4); 562 roundToDecimals (cx, 4);
563 RoundToDecimals (cy, 4); 563 roundToDecimals (cy, 4);
564 564
565 // Create the vertex from the coordinates 565 // Create the vertex from the coordinates
566 pos3d.setCoordinate (axisX, cx); 566 pos3d.setCoordinate (axisX, cx);
567 pos3d.setCoordinate (axisY, cy); 567 pos3d.setCoordinate (axisY, cy);
568 pos3d.setCoordinate ((Axis) (3 - axisX - axisY), getDepthValue()); 568 pos3d.setCoordinate ((Axis) (3 - axisX - axisY), getDepthValue());
614 614
615 // ============================================================================= 615 // =============================================================================
616 // 616 //
617 void GLRenderer::paintEvent (QPaintEvent*) 617 void GLRenderer::paintEvent (QPaintEvent*)
618 { 618 {
619 doMakeCurrent(); 619 makeCurrent();
620 m_virtualWidth = zoom(); 620 m_virtualWidth = zoom();
621 m_virtualHeight = (m_height * m_virtualWidth) / m_width; 621 m_virtualHeight = (m_height * m_virtualWidth) / m_width;
622 initGLData(); 622 initGLData();
623 drawGLScene(); 623 drawGLScene();
624 624
625 QPainter paint (this); 625 QPainter painter (this);
626 QFontMetrics metrics = QFontMetrics (QFont()); 626 QFontMetrics metrics = QFontMetrics (QFont());
627 paint.setRenderHint (QPainter::HighQualityAntialiasing); 627 painter.setRenderHint (QPainter::Antialiasing);
628 painter.setRenderHint (QPainter::HighQualityAntialiasing);
628 629
629 // If we wish to only draw the brick, stop here 630 // If we wish to only draw the brick, stop here
630 if (isDrawOnly()) 631 if (isDrawOnly())
631 return; 632 return;
632 633
634 if (not isPicking()) 635 if (not isPicking())
635 { 636 {
636 QString text = format ("Rotation: (%1°, %2°, %3°)\nPanning: (%4, %5), Zoom: %6", 637 QString text = format ("Rotation: (%1°, %2°, %3°)\nPanning: (%4, %5), Zoom: %6",
637 rotation(X), rotation(Y), rotation(Z), panning(X), panning(Y), zoom()); 638 rotation(X), rotation(Y), rotation(Z), panning(X), panning(Y), zoom());
638 QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text); 639 QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text);
639 paint.setPen (textPen()); 640 painter.setPen (textPen());
640 paint.drawText ((width() - textSize.width()) / 2, height() - textSize.height(), textSize.width(), 641 painter.drawText ((width() - textSize.width()) / 2, height() - textSize.height(), textSize.width(),
641 textSize.height(), Qt::AlignCenter, text); 642 textSize.height(), Qt::AlignCenter, text);
642 } 643 }
643 #endif 644 #endif
644 645
645 if (camera() != EFreeCamera and not isPicking()) 646 if (camera() != EFreeCamera and not isPicking())
651 { 652 {
652 QPoint v0 = convert3dTo2d (currentDocumentData().overlays[camera()].v0); 653 QPoint v0 = convert3dTo2d (currentDocumentData().overlays[camera()].v0);
653 QPoint v1 = convert3dTo2d (currentDocumentData().overlays[camera()].v1); 654 QPoint v1 = convert3dTo2d (currentDocumentData().overlays[camera()].v1);
654 QRect targetRect (v0.x(), v0.y(), qAbs (v1.x() - v0.x()), qAbs (v1.y() - v0.y())); 655 QRect targetRect (v0.x(), v0.y(), qAbs (v1.x() - v0.x()), qAbs (v1.y() - v0.y()));
655 QRect sourceRect (0, 0, overlay.img->width(), overlay.img->height()); 656 QRect sourceRect (0, 0, overlay.img->width(), overlay.img->height());
656 paint.drawImage (targetRect, *overlay.img, sourceRect); 657 painter.drawImage (targetRect, *overlay.img, sourceRect);
657 } 658 }
658 659
659 // Paint the coordinates onto the screen. 660 // Paint the coordinates onto the screen.
660 QString text = format (tr ("X: %1, Y: %2, Z: %3"), m_position3D[X], m_position3D[Y], m_position3D[Z]); 661 QString text = format (tr ("X: %1, Y: %2, Z: %3"), m_position3D[X], m_position3D[Y], m_position3D[Z]);
661 QFontMetrics metrics = QFontMetrics (font()); 662 QFontMetrics metrics = QFontMetrics (font());
662 QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text); 663 QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text);
663 paint.setPen (textPen()); 664 painter.setPen (textPen());
664 paint.drawText (m_width - textSize.width(), m_height - 16, textSize.width(), 665 painter.drawText (m_width - textSize.width(), m_height - 16, textSize.width(),
665 textSize.height(), Qt::AlignCenter, text); 666 textSize.height(), Qt::AlignCenter, text);
666 } 667 }
667 668
668 if (not isPicking()) 669 if (not isPicking())
669 { 670 {
670 // Draw edit mode HUD 671 // Draw edit mode HUD
671 m_currentEditMode->render (paint); 672 m_currentEditMode->render (painter);
672 673
673 // Draw a background for the selected camera 674 // Draw a background for the selected camera
674 paint.setPen (m_thinBorderPen); 675 painter.setPen (m_thinBorderPen);
675 paint.setBrush (QBrush (QColor (0, 128, 160, 128))); 676 painter.setBrush (QBrush (QColor (0, 128, 160, 128)));
676 paint.drawRect (m_cameraIcons[camera()].selRect); 677 painter.drawRect (m_cameraIcons[camera()].selRect);
677 678
678 // Draw the camera icons 679 // Draw the camera icons
679 for (CameraIcon& info : m_cameraIcons) 680 for (CameraIcon& info : m_cameraIcons)
680 { 681 {
681 // Don't draw the free camera icon when we can't use the free camera 682 // Don't draw the free camera icon when we can't use the free camera
682 if (&info == &m_cameraIcons[EFreeCamera] and not m_currentEditMode->allowFreeCamera()) 683 if (&info == &m_cameraIcons[EFreeCamera] and not m_currentEditMode->allowFreeCamera())
683 continue; 684 continue;
684 685
685 paint.drawPixmap (info.targetRect, *info.image, info.sourceRect); 686 painter.drawPixmap (info.targetRect, *info.image, info.sourceRect);
686 } 687 }
687 688
688 // Draw a label for the current camera in the bottom left corner 689 // Draw a label for the current camera in the bottom left corner
689 { 690 {
690 const int margin = 4; 691 const int margin = 4;
691 paint.setPen (textPen()); 692 painter.setPen (textPen());
692 paint.drawText (QPoint (margin, height() - (margin + metrics.descent())), currentCameraName()); 693 painter.drawText (QPoint (margin, height() - (margin + metrics.descent())), currentCameraName());
693 } 694 }
694 695
695 // Tool tips 696 // Tool tips
696 if (m_drawToolTip) 697 if (m_drawToolTip)
697 { 698 {
710 QColor penColor = textPen().color(); 711 QColor penColor = textPen().color();
711 712
712 for (const MessageManager::Line& line : messageLog()->getLines()) 713 for (const MessageManager::Line& line : messageLog()->getLines())
713 { 714 {
714 penColor.setAlphaF (line.alpha); 715 penColor.setAlphaF (line.alpha);
715 paint.setPen (penColor); 716 painter.setPen (penColor);
716 paint.drawText (QPoint (margin, y + margin + metrics.ascent()), line.text); 717 painter.drawText (QPoint (margin, y + margin + metrics.ascent()), line.text);
717 y += metrics.height(); 718 y += metrics.height();
718 } 719 }
719 } 720 }
720 } 721 }
721 722
877 878
878 // ============================================================================= 879 // =============================================================================
879 // 880 //
880 void GLRenderer::wheelEvent (QWheelEvent* ev) 881 void GLRenderer::wheelEvent (QWheelEvent* ev)
881 { 882 {
882 doMakeCurrent(); 883 makeCurrent();
883
884 zoomNotch (ev->delta() > 0); 884 zoomNotch (ev->delta() > 0);
885 zoom() = qBound (0.01, zoom(), 10000.0); 885 zoom() = qBound (0.01, zoom(), 10000.0);
886 m_isCameraMoving = true; 886 m_isCameraMoving = true;
887 update(); 887 update();
888 ev->accept(); 888 ev->accept();
927 927
928 // ============================================================================= 928 // =============================================================================
929 // 929 //
930 void GLRenderer::pick (QRect const& range, bool additive) 930 void GLRenderer::pick (QRect const& range, bool additive)
931 { 931 {
932 doMakeCurrent(); 932 makeCurrent();
933 933
934 // Clear the selection if we do not wish to add to it. 934 // Clear the selection if we do not wish to add to it.
935 if (not additive) 935 if (not additive)
936 { 936 {
937 LDObjectList oldSelection = selectedObjects(); 937 LDObjectList oldSelection = selectedObjects();
958 const int areawidth = (x1 - x0); 958 const int areawidth = (x1 - x0);
959 const int areaheight = (y1 - y0); 959 const int areaheight = (y1 - y0);
960 const qint32 numpixels = areawidth * areaheight; 960 const qint32 numpixels = areawidth * areaheight;
961 961
962 // Allocate space for the pixel data. 962 // Allocate space for the pixel data.
963 uchar* const pixeldata = new uchar[4 * numpixels]; 963 QVector<unsigned char> pixeldata (4 * numpixels);
964 uchar* pixelptr = &pixeldata[0]; 964 unsigned char* pixelcursor = pixeldata.data();
965 965
966 // Read pixels from the color buffer. 966 // Read pixels from the color buffer.
967 glReadPixels (x0, m_height - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata); 967 glReadPixels (x0, m_height - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata.data());
968 968
969 LDObject* removedObj = nullptr; 969 LDObject* removedObj = nullptr;
970 QList<qint32> indices; 970 QSet<qint32> indices;
971 971
972 // Go through each pixel read and add them to the selection. 972 // Go through each pixel read and add them to the selection.
973 // Note: black is background, those indices are skipped. 973 // Note: black is background, those indices are skipped.
974 for (qint32 i = 0; i < numpixels; ++i) 974 for (qint32 i = 0; i < numpixels; ++i)
975 { 975 {
976 qint32 idx = 976 qint32 idx = (pixelcursor[0] * 0x10000) + (pixelcursor[1] * 0x100) + pixelcursor[2];
977 (*(pixelptr + 0) * 0x10000) + 977 pixelcursor += 4;
978 (*(pixelptr + 1) * 0x100) +
979 *(pixelptr + 2);
980 pixelptr += 4;
981 978
982 if (idx != 0) 979 if (idx != 0)
983 indices << idx; 980 indices << idx;
984 } 981 }
985
986 removeDuplicates (indices);
987 982
988 for (qint32 idx : indices) 983 for (qint32 idx : indices)
989 { 984 {
990 LDObject* obj = LDObject::fromID (idx); 985 LDObject* obj = LDObject::fromID (idx);
991 986
1005 } 1000 }
1006 1001
1007 obj->select(); 1002 obj->select();
1008 } 1003 }
1009 1004
1010 delete[] pixeldata;
1011
1012 // Update everything now. 1005 // Update everything now.
1013 m_window->updateSelection(); 1006 m_window->updateSelection();
1014 1007
1015 // Recompile the objects now to update their color 1008 // Recompile the objects now to update their color
1016 for (LDObject* obj : selectedObjects()) 1009 for (LDObject* obj : selectedObjects())
1022 setPicking (false); 1015 setPicking (false);
1023 repaint(); 1016 repaint();
1024 } 1017 }
1025 1018
1026 // 1019 //
1027 // Simpler version of GLRenderer::pick which simply picks whatever object on the screen 1020 // Simpler version of GLRenderer::pick which simply picks whatever object on the cursor
1028 // 1021 //
1029 LDObject* GLRenderer::pickOneObject (int mouseX, int mouseY) 1022 LDObject* GLRenderer::pickOneObject (int mouseX, int mouseY)
1030 { 1023 {
1031 uchar pixel[4]; 1024 uchar pixel[4];
1032 doMakeCurrent(); 1025 makeCurrent();
1033 setPicking (true); 1026 setPicking (true);
1034 drawGLScene(); 1027 drawGLScene();
1035 glReadPixels (mouseX, m_height - mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); 1028 glReadPixels (mouseX, m_height - mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
1036 LDObject* obj = LDObject::fromID ((pixel[0] * 0x10000) + (pixel[1] * 0x100) + pixel[2]); 1029 LDObject* obj = LDObject::fromID ((pixel[0] * 0x10000) + (pixel[1] * 0x100) + pixel[2]);
1037 setPicking (false); 1030 setPicking (false);
1627 QPointF const& GLRenderer::mousePositionF() const 1620 QPointF const& GLRenderer::mousePositionF() const
1628 { 1621 {
1629 return m_mousePositionF; 1622 return m_mousePositionF;
1630 } 1623 }
1631 1624
1632 void GLRenderer::doMakeCurrent() 1625 void GLRenderer::makeCurrent()
1633 { 1626 {
1634 makeCurrent(); 1627 QGLWidget::makeCurrent();
1635 initializeOpenGLFunctions(); 1628 initializeOpenGLFunctions();
1636 } 1629 }
1637 1630
1638 int GLRenderer::depthNegateFactor() const 1631 int GLRenderer::depthNegateFactor() const
1639 { 1632 {

mercurial