556 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
556 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
557 // ========================================================================= // |
557 // ========================================================================= // |
558 void GLRenderer::pick (uint mx, uint my, bool add) { |
558 void GLRenderer::pick (uint mx, uint my, bool add) { |
559 GLint viewport[4]; |
559 GLint viewport[4]; |
560 |
560 |
|
561 // Clear the selection if we do not wish to add to it. |
561 if (add == false) { |
562 if (add == false) { |
562 // Clear the selection if we don't wish to add to it. |
|
563 std::vector<LDObject*> paOldSelection = g_ForgeWindow->paSelection; |
563 std::vector<LDObject*> paOldSelection = g_ForgeWindow->paSelection; |
564 g_ForgeWindow->paSelection.clear (); |
564 g_ForgeWindow->paSelection.clear (); |
565 |
565 |
566 // Recompile the prior selection to remove the highlight color |
566 // Recompile the prior selection to remove the highlight color |
567 for (LDObject* obj : paOldSelection) |
567 for (LDObject* obj : paOldSelection) |
599 x0 = max<short> (0, x0); |
602 x0 = max<short> (0, x0); |
600 y0 = max<short> (0, y0); |
603 y0 = max<short> (0, y0); |
601 x1 = min<short> (x1, width); |
604 x1 = min<short> (x1, width); |
602 y1 = min<short> (y1, height); |
605 y1 = min<short> (y1, height); |
603 |
606 |
604 short areawidth = (x1 - x0); |
607 const short areawidth = (x1 - x0); |
605 short areaheight = (y1 - y0); |
608 const short areaheight = (y1 - y0); |
606 |
|
607 const long numpixels = areawidth * areaheight; |
609 const long numpixels = areawidth * areaheight; |
|
610 |
|
611 // Allocate space for the pixel data. |
608 uchar* const pixeldata = new uchar[4 * numpixels]; |
612 uchar* const pixeldata = new uchar[4 * numpixels]; |
609 uchar* pixelptr = &pixeldata[0]; |
613 uchar* pixelptr = &pixeldata[0]; |
610 |
614 |
611 assert (viewport[3] == height); |
615 assert (viewport[3] == height); |
612 |
616 |
|
617 // Read pixels from the color buffer. |
613 glReadPixels (x0, viewport[3] - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata); |
618 glReadPixels (x0, viewport[3] - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata); |
614 |
619 |
|
620 // Go through each pixel read and add them to the selection. |
615 for (long i = 0; i < numpixels; ++i) { |
621 for (long i = 0; i < numpixels; ++i) { |
616 uint32 idx = |
622 uint32 idx = |
617 (*(pixelptr) * 0x10000) + |
623 (*(pixelptr) * 0x10000) + |
618 (*(pixelptr + 1) * 0x00100) + |
624 (*(pixelptr + 1) * 0x00100) + |
619 (*(pixelptr + 2) * 0x00001); |
625 (*(pixelptr + 2) * 0x00001); |
626 g_ForgeWindow->paSelection.push_back (obj); |
632 g_ForgeWindow->paSelection.push_back (obj); |
627 } |
633 } |
628 |
634 |
629 delete[] pixeldata; |
635 delete[] pixeldata; |
630 |
636 |
|
637 // Remove duplicate entries. For this to be effective, the vector must be |
|
638 // sorted first. |
631 std::vector<LDObject*>& sel = g_ForgeWindow->paSelection; |
639 std::vector<LDObject*>& sel = g_ForgeWindow->paSelection; |
632 std::sort (sel.begin(), sel.end ()); |
640 std::sort (sel.begin(), sel.end ()); |
633 std::vector<LDObject*>::iterator pos = std::unique (sel.begin (), sel.end ()); |
641 std::vector<LDObject*>::iterator pos = std::unique (sel.begin (), sel.end ()); |
634 sel.resize (std::distance (sel.begin (), pos)); |
642 sel.resize (std::distance (sel.begin (), pos)); |
635 |
643 |
|
644 // Update everything now. |
636 g_ForgeWindow->buildObjList (); |
645 g_ForgeWindow->buildObjList (); |
637 |
646 |
638 picking = false; |
647 picking = false; |
639 rangepick = false; |
648 rangepick = false; |
640 glEnable (GL_DITHER); |
649 glEnable (GL_DITHER); |