| 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); |