699 m_config->setCamera(static_cast<int>(camera)); |
699 m_config->setCamera(static_cast<int>(camera)); |
700 } |
700 } |
701 } |
701 } |
702 |
702 |
703 /* |
703 /* |
|
704 * Resolves a pixel pointer to an RGB color. |
|
705 * pixel[0..2] must be valid. |
|
706 */ |
|
707 static QRgb colorFromPixel(uint8_t* pixel) |
|
708 { |
|
709 return pixel[0] << 16 | pixel[1] << 8 | pixel[2] | 0xff000000; |
|
710 } |
|
711 |
|
712 /* |
704 * Returns the set of objects found in the specified pixel area. |
713 * Returns the set of objects found in the specified pixel area. |
705 */ |
714 */ |
706 QItemSelection GLRenderer::pick(const QRect& range) |
715 QItemSelection GLRenderer::pick(const QRect& range) |
707 { |
716 { |
708 makeCurrent(); |
717 makeCurrent(); |
731 pixelData.resize(4 * numpixels); |
740 pixelData.resize(4 * numpixels); |
732 |
741 |
733 // Read pixels from the color buffer. |
742 // Read pixels from the color buffer. |
734 glReadPixels(x0, height() - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data()); |
743 glReadPixels(x0, height() - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data()); |
735 |
744 |
736 QSet<qint32> ids; |
745 QSet<QRgb> pixelColors; |
737 |
746 |
738 // Go through each pixel read and add them to the selection. |
747 // Go through each pixel read and add them to the selection. |
739 // Each pixel maps to an LDObject index injectively. |
748 // Each pixel maps to an LDObject injectively. |
740 // Note: black is background, those indices are skipped. |
749 // Note: black is background, those indices are skipped. |
741 for (unsigned char *pixelCursor = pixelData.begin(); pixelCursor < pixelData.end(); pixelCursor += 4) |
750 for (int i : ::range(0, 4, pixelData.size() - 4)) |
742 { |
751 { |
743 qint32 id = pixelCursor[0] * 0x10000 + pixelCursor[1] * 0x100 + pixelCursor[2] * 0x1; |
752 QRgb color = colorFromPixel(&pixelData[i]); |
744 if (id != 0) |
753 |
745 ids.insert(id); |
754 if (color != BlackRgb) |
|
755 pixelColors.insert(color); |
746 } |
756 } |
747 |
757 |
748 // For each index read, resolve the LDObject behind it and add it to the selection. |
758 // For each index read, resolve the LDObject behind it and add it to the selection. |
749 for (qint32 id : ids) |
759 for (QRgb color : pixelColors) |
750 { |
760 { |
751 QModelIndex index = m_model->indexFromId(id); |
761 QModelIndex index = m_model->objectByPickingColor(color); |
752 |
762 |
753 if (index.isValid()) |
763 if (index.isValid()) |
754 result.select(index, index); |
764 result.select(index, index); |
755 } |
765 } |
756 |
766 |
767 makeCurrent(); |
777 makeCurrent(); |
768 setPicking(true); |
778 setPicking(true); |
769 drawGLScene(); |
779 drawGLScene(); |
770 unsigned char pixel[4]; |
780 unsigned char pixel[4]; |
771 glReadPixels(mouseX, height() - mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); |
781 glReadPixels(mouseX, height() - mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); |
772 QModelIndex result = m_model->indexFromId(pixel[0] * 0x10000 + pixel[1] * 0x100 + pixel[2]); |
782 QModelIndex result = m_model->objectByPickingColor(colorFromPixel(pixel)); |
773 setPicking(false); |
783 setPicking(false); |
774 repaint(); |
784 repaint(); |
775 return result; |
785 return result; |
776 } |
786 } |
777 |
787 |
836 void GLRenderer::zoomToFit() |
846 void GLRenderer::zoomToFit() |
837 { |
847 { |
838 currentCamera().setZoom(30.0f); |
848 currentCamera().setZoom(30.0f); |
839 bool lastfilled = false; |
849 bool lastfilled = false; |
840 bool firstrun = true; |
850 bool firstrun = true; |
841 enum { black = 0xFF000000 }; |
|
842 bool inward = true; |
851 bool inward = true; |
843 int runaway = 50; |
852 int runaway = 50; |
844 |
853 |
845 // Use the pick list while drawing the scene, this way we can tell whether borders |
854 // Use the pick list while drawing the scene, this way we can tell whether borders |
846 // are background or not. |
855 // are background or not. |
937 if (not m_isCameraMoving and m_config->highlightObjectBelowCursor()) |
946 if (not m_isCameraMoving and m_config->highlightObjectBelowCursor()) |
938 { |
947 { |
939 setPicking (true); |
948 setPicking (true); |
940 drawGLScene(); |
949 drawGLScene(); |
941 setPicking (false); |
950 setPicking (false); |
942 |
|
943 unsigned char pixel[4]; |
951 unsigned char pixel[4]; |
944 glReadPixels (m_mousePosition.x(), height() - m_mousePosition.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel[0]); |
952 glReadPixels( |
945 qint32 id = pixel[0] * 0x10000 | pixel[1] * 0x100 | pixel[2]; |
953 m_mousePosition.x(), |
946 |
954 height() - m_mousePosition.y(), |
947 if (id != 0) |
955 1, |
948 newIndex = model()->indexFromId(id); |
956 1, |
|
957 GL_RGBA, |
|
958 GL_UNSIGNED_BYTE, |
|
959 &pixel[0] |
|
960 ); |
|
961 newIndex = model()->objectByPickingColor(colorFromPixel(pixel)); |
949 } |
962 } |
950 |
963 |
951 if (newIndex != oldIndex) |
964 if (newIndex != oldIndex) |
952 { |
965 { |
953 m_objectAtCursor = newIndex; |
966 m_objectAtCursor = newIndex; |