summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerwindow.cpp')
-rw-r--r--indra/newview/llviewerwindow.cpp994
1 files changed, 478 insertions, 516 deletions
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 4c575ff139..0296aee8ca 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -203,8 +203,32 @@ extern S32 gJamesInt;
LLViewerWindow *gViewerWindow = NULL;
LLVelocityBar *gVelocityBar = NULL;
+LLVector3d gLastHitPosGlobal;
+LLVector3d gLastHitObjectOffset;
+LLUUID gLastHitObjectID;
+S32 gLastHitObjectFace = -1;
+BOOL gLastHitLand = FALSE;
+F32 gLastHitUCoord;
+F32 gLastHitVCoord;
+
+
+LLVector3d gLastHitNonFloraPosGlobal;
+LLVector3d gLastHitNonFloraObjectOffset;
+LLUUID gLastHitNonFloraObjectID;
+S32 gLastHitNonFloraObjectFace = -1;
+BOOL gLastHitParcelWall = FALSE;
+
+S32 gLastHitUIElement = 0;
+LLHUDIcon* gLastHitHUDIcon = NULL;
BOOL gDebugSelect = FALSE;
+U8 gLastPickAlpha = 255;
+BOOL gUseGLPick = FALSE;
+
+// On the next pick pass (whenever that happens)
+// should we try to pick individual faces?
+// Cleared to FALSE every time a pick happens.
+BOOL gPickFaces = FALSE;
LLFrameTimer gMouseIdleTimer;
LLFrameTimer gAwayTimer;
@@ -215,11 +239,6 @@ BOOL gShowOverlayTitle = FALSE;
BOOL gPickTransparent = TRUE;
BOOL gDebugFastUIRender = FALSE;
-LLViewerObject* gDebugRaycastObject = NULL;
-LLVector3 gDebugRaycastIntersection;
-LLVector2 gDebugRaycastTexCoord;
-LLVector3 gDebugRaycastNormal;
-LLVector3 gDebugRaycastBinormal;
// HUD display lines in lower right
BOOL gDisplayWindInfo = FALSE;
@@ -237,6 +256,9 @@ const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before co
const F32 MAX_FAST_FRAME_TIME = 0.5f;
const F32 FAST_FRAME_INCREMENT = 0.1f;
+const S32 PICK_HALF_WIDTH = 5;
+const S32 PICK_DIAMETER = 2 * PICK_HALF_WIDTH+1;
+
const F32 MIN_DISPLAY_SCALE = 0.85f;
const S32 CONSOLE_BOTTOM_PAD = 40;
@@ -1487,8 +1509,8 @@ LLViewerWindow::LLViewerWindow(
mToolStored( NULL ),
mSuppressToolbox( FALSE ),
mHideCursorPermanent( FALSE ),
- mIgnoreActivate( FALSE ),
- mHoverPick()
+ mPickPending(FALSE),
+ mIgnoreActivate( FALSE )
{
// Default to application directory.
LLViewerWindow::sSnapshotBaseName = "Snapshot";
@@ -1596,6 +1618,8 @@ LLViewerWindow::LLViewerWindow(
mCurrentMousePoint.mX = getWindowWidth() / 2;
mCurrentMousePoint.mY = getWindowHeight() / 2;
+ mPickBuffer = new U8[PICK_DIAMETER * PICK_DIAMETER * 4];
+
gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
mOverlayTitle = gSavedSettings.getString("OverlayTitle");
// Can't have spaces in settings.ini strings, so use underscores instead and convert them.
@@ -2008,6 +2032,9 @@ LLViewerWindow::~LLViewerWindow()
LLViewerImage::cleanupClass();
+ delete[] mPickBuffer;
+ mPickBuffer = NULL;
+
llinfos << "Cleaning up select manager" << llendl;
LLSelectMgr::getInstance()->cleanup();
@@ -2706,10 +2733,6 @@ BOOL LLViewerWindow::handlePerFrameHover()
LLView::sMouseHandlerMessage.clear();
- S32 x = mCurrentMousePoint.mX;
- S32 y = mCurrentMousePoint.mY;
- MASK mask = gKeyboard->currentMask(TRUE);
-
//RN: fix for asynchronous notification of mouse leaving window not working
LLCoordWindow mouse_pos;
mWindow->getCursorPosition(&mouse_pos);
@@ -2725,7 +2748,6 @@ BOOL LLViewerWindow::handlePerFrameHover()
mMouseInWindow = TRUE;
}
-
S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
@@ -2756,6 +2778,10 @@ BOOL LLViewerWindow::handlePerFrameHover()
return TRUE;
}
+ S32 x = mCurrentMousePoint.mX;
+ S32 y = mCurrentMousePoint.mY;
+ MASK mask = gKeyboard->currentMask(TRUE);
+
// clean up current focus
LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
if (cur_focus)
@@ -3097,41 +3123,10 @@ BOOL LLViewerWindow::handlePerFrameHover()
LLSelectMgr::getInstance()->deselectUnused();
}
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
- {
- gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1,
- NULL,
- &gDebugRaycastIntersection,
- &gDebugRaycastTexCoord,
- &gDebugRaycastNormal,
- &gDebugRaycastBinormal);
- }
-
- static U16 frame_counter = 0;
- static S32 previous_x = -1;
- static S32 previous_y = -1;
-
- if (((previous_x != x) || (previous_y != y)) ||
- ((gSavedSettings.getBOOL("PerFrameHoverPick"))
- && ((frame_counter % gSavedSettings.getS32("PerFrameHoverPickCount")) == 0)))
- {
- pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE);
- }
- frame_counter++;
- previous_x = x;
- previous_y = y;
-
return handled;
}
-/* static */
-void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info)
-{
- gViewerWindow->mHoverPick = pick_info;
-}
-
-
void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
{
// Store last mouse location.
@@ -3225,7 +3220,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
glPushMatrix();
if (selection->getSelectType() == SELECT_TYPE_HUD)
{
- F32 zoom = gAgent.mHUDCurZoom;
+ F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
glScalef(zoom, zoom, zoom);
}
@@ -3377,14 +3372,19 @@ BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewe
return intersect;
}
-void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent, BOOL get_surface_info)
+void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent, BOOL pick_parcel_walls)
{
if (gNoRender)
{
return;
}
- // push back pick info object
+ glClear(GL_DEPTH_BUFFER_BIT);
+ gDepthDirty = TRUE;
+
+ S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]);
+ S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]);
+
BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible();
if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
{
@@ -3392,44 +3392,29 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback
// "Show Debug Alpha" means no object actually transparent
pick_transparent = TRUE;
}
+ gPickTransparent = pick_transparent;
- // center initial pick frame buffer region under mouse cursor
- // since that area is guaranteed to be onscreen and hence a valid
- // part of the framebuffer
- if (mPicks.empty())
- {
- mPickScreenRegion.setCenterAndSize(x, y_from_bot, PICK_DIAMETER, PICK_DIAMETER);
-
- if (mPickScreenRegion.mLeft < 0) mPickScreenRegion.translate(-mPickScreenRegion.mLeft, 0);
- if (mPickScreenRegion.mBottom < 0) mPickScreenRegion.translate(0, -mPickScreenRegion.mBottom);
- if (mPickScreenRegion.mRight > mWindowRect.getWidth() ) mPickScreenRegion.translate(mWindowRect.getWidth() - mPickScreenRegion.mRight, 0);
- if (mPickScreenRegion.mTop > mWindowRect.getHeight() ) mPickScreenRegion.translate(0, mWindowRect.getHeight() - mPickScreenRegion.mTop);
- }
+ gUseGLPick = FALSE;
+ mPickCallback = callback;
- // set frame buffer region for picking results
- // stack multiple picks left to right
- LLRect screen_region = mPickScreenRegion;
- screen_region.translate(mPicks.size() * PICK_DIAMETER, 0);
-
- LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, get_surface_info, callback);
+ // Default to not hitting anything
+ gLastHitPosGlobal.zeroVec();
+ gLastHitObjectOffset.zeroVec();
+ gLastHitObjectID.setNull();
+ gLastHitObjectFace = -1;
- schedulePick(pick);
-}
+ gLastHitNonFloraPosGlobal.zeroVec();
+ gLastHitNonFloraObjectOffset.zeroVec();
+ gLastHitNonFloraObjectID.setNull();
+ gLastHitNonFloraObjectFace = -1;
-void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
-{
- llassert_always(pick_info.mScreenRegion.notNull());
- mPicks.push_back(pick_info);
-
- S32 scaled_x = llround((F32)pick_info.mMousePt.mX * mDisplayScale.mV[VX]);
- S32 scaled_y = llround((F32)pick_info.mMousePt.mY * mDisplayScale.mV[VY]);
+ gLastHitParcelWall = FALSE;
- // Default to not hitting anything
LLCamera pick_camera;
pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin());
pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(),
LLViewerCamera::getInstance()->getUpAxis(),
- LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(pick_info.mMousePt.mX, pick_info.mMousePt.mY));
+ LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot));
pick_camera.setView(0.5f*DEG_TO_RAD);
pick_camera.setNear(LLViewerCamera::getInstance()->getNear());
pick_camera.setFar(LLViewerCamera::getInstance()->getFar());
@@ -3446,38 +3431,117 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
glPushMatrix();
glLoadIdentity();
- // clear work area
- {
- LLGLState scissor_state(GL_SCISSOR_TEST);
- scissor_state.enable();
- glScissor(pick_info.mScreenRegion.mLeft, pick_info.mScreenRegion.mBottom, pick_info.mScreenRegion.getWidth(), pick_info.mScreenRegion.getHeight());
+ // build perspective transform and picking viewport
+ // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point.
+ // Don't limit the select distance for this pick.
+ LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - (PICK_HALF_WIDTH + 2), scaled_y - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4, FALSE);
+ // make viewport big enough to handle antialiased frame buffers
+ gGLViewport[0] = scaled_x - (PICK_HALF_WIDTH + 2);
+ gGLViewport[1] = scaled_y - (PICK_HALF_WIDTH + 2);
+ gGLViewport[2] = PICK_DIAMETER + 4;
+ gGLViewport[3] = PICK_DIAMETER + 4;
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+ LLViewerCamera::updateFrustumPlanes(pick_camera);
+ stop_glerror();
+
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ // Draw the objects so the user can select them.
+ // The starting ID is 1, since land is zero.
+ gObjectList.renderObjectsForSelect(pick_camera, pick_parcel_walls);
+
+ stop_glerror();
+
+ // restore drawing state
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ setupViewport();
+
+ mPickPoint.set(x, y_from_bot);
+ mPickOffset.set(0, 0);
+ mPickMask = mask;
+ mPickPending = TRUE;
+
+ // delay further event processing until we receive results of pick
+ mWindow->delayInputProcessing();
+}
+
+void LLViewerWindow::hitUIElementImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask))
+{
+ // Performs the GL UI pick.
+ // Stores its results in global, gLastHitUIElement
+ if (gNoRender)
+ {
+ return;
}
- // build perspective transform and picking viewport
+ hitUIElementAsync(x, y, gKeyboard->currentMask(TRUE), NULL);
+ performPick();
+ if (callback)
+ {
+ callback(x, y, gKeyboard->currentMask(TRUE));
+ }
+}
+
+//RN: this currently doesn't do anything
+void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask))
+{
+ if (gNoRender)
+ {
+ return;
+ }
+
+// F32 delta_time = gAlphaFadeTimer.getElapsedTimeAndResetF32();
+
+ gUseGLPick = FALSE;
+ mPickCallback = callback;
+
+ // Default to not hitting anything
+ gLastHitUIElement = 0;
+
+ LLCamera pick_camera;
+ pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin());
+ pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(),
+ LLViewerCamera::getInstance()->getUpAxis(),
+ LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot));
+ pick_camera.setView(0.5f*DEG_TO_RAD);
+ pick_camera.setNear(LLViewerCamera::getInstance()->getNear());
+ pick_camera.setFar(LLViewerCamera::getInstance()->getFar());
+ pick_camera.setAspect(1.f);
+
+ // save our drawing state
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ // build orthogonal transform and picking viewport
// Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point.
// Don't limit the select distance for this pick.
- LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, FALSE);
+ setup2DRender();
+ const LLVector2& display_scale = getDisplayScale();
+ glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
- // render for object picking
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
// make viewport big enough to handle antialiased frame buffers
- gGLViewport[0] = pick_info.mScreenRegion.mLeft;
- gGLViewport[1] = pick_info.mScreenRegion.mBottom;
- gGLViewport[2] = pick_info.mScreenRegion.getWidth();
- gGLViewport[3] = pick_info.mScreenRegion.getHeight();
-
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- LLViewerCamera::updateFrustumPlanes(pick_camera);
+ glViewport(x - (PICK_HALF_WIDTH + 2), y_from_bot - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4);
stop_glerror();
+ glClearColor(0.f, 0.f, 0.f, 0.f);
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
// Draw the objects so the user can select them.
// The starting ID is 1, since land is zero.
- LLRect pick_region;
- pick_region.setOriginAndSize(scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER);
- gObjectList.renderObjectsForSelect(pick_camera, pick_region, FALSE, pick_info.mPickTransparent);
+ //drawForSelect();
stop_glerror();
@@ -3487,121 +3551,309 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
- setup3DRender();
- setup2DRender();
setupViewport();
- // delay further event processing until we receive results of pick
- mWindow->delayInputProcessing();
+ mPickPoint.set(x, y_from_bot);
+ mPickOffset.set(0, 0);
+ mPickMask = mask;
+ mPickPending = TRUE;
}
-
void LLViewerWindow::performPick()
{
- if (gNoRender)
+ if (gNoRender || !mPickPending)
{
return;
}
- if (!mPicks.empty())
+ mPickPending = FALSE;
+ U32 te_offset = NO_FACE;
+
+ // find pick region that is fully onscreen
+ LLCoordGL scaled_pick_point = mPickPoint;
+ scaled_pick_point.mX = llclamp(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), PICK_HALF_WIDTH, getWindowDisplayWidth() - PICK_HALF_WIDTH);
+ scaled_pick_point.mY = llclamp(llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]), PICK_HALF_WIDTH, getWindowDisplayHeight() - PICK_HALF_WIDTH);
+
+ glReadPixels(scaled_pick_point.mX - PICK_HALF_WIDTH, scaled_pick_point.mY - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
+
+ S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH;
+ S32 name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
+ gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
+
+ if (name >= (S32)GL_NAME_UI_RESERVED && name < (S32)GL_NAME_INDEX_OFFSET)
+ {
+ // hit a UI element
+ gLastHitUIElement = name;
+ if (mPickCallback)
+ {
+ mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask);
+ }
+ }
+
+ //imdebug("rgba rbga=bbba b=8 w=%d h=%d %p", PICK_DIAMETER, PICK_DIAMETER, mPickBuffer);
+
+ S32 x_offset = mPickPoint.mX - llround((F32)scaled_pick_point.mX / mDisplayScale.mV[VX]);
+ S32 y_offset = mPickPoint.mY - llround((F32)scaled_pick_point.mY / mDisplayScale.mV[VY]);
+
+
+ // we hit nothing, scan surrounding pixels for something useful
+ if (!name)
{
- std::vector<LLPickInfo>::iterator pick_it;
- for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
+ S32 closest_distance = 10000;
+ //S32 closest_pick_name = 0;
+ for (S32 col = 0; col < PICK_DIAMETER; col++)
{
- pick_it->fetchResults();
+ for (S32 row = 0; row < PICK_DIAMETER; row++)
+ {
+ S32 distance_squared = (llabs(col - x_offset - PICK_HALF_WIDTH) * llabs(col - x_offset - PICK_HALF_WIDTH)) + (llabs(row - y_offset - PICK_HALF_WIDTH) * llabs(row - y_offset - PICK_HALF_WIDTH));
+ pixel_index = row * PICK_DIAMETER + col;
+ S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
+ gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
+ if (test_name && distance_squared < closest_distance)
+ {
+ closest_distance = distance_squared;
+ name = test_name;
+ gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
+ mPickOffset.mX = col - PICK_HALF_WIDTH;
+ mPickOffset.mY = row - PICK_HALF_WIDTH;
+ }
+ }
}
+ }
- mLastPick = mPicks.back();
- mPicks.clear();
+ if (name)
+ {
+ mPickPoint.mX += llround((F32)mPickOffset.mX * mDisplayScale.mV[VX]);
+ mPickPoint.mY += llround((F32)mPickOffset.mY * mDisplayScale.mV[VY]);
}
-}
+ if (gPickFaces)
+ {
+ te_offset = ((U32)name >> 20);
+ name &= 0x000fffff;
+ // don't clear gPickFaces, as we still need to check for UV coordinates
+ }
-// Performs the GL object/land pick.
-LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent)
-{
- if (gNoRender)
+ LLViewerObject *objectp = NULL;
+
+ // Frontmost non-foreground object that isn't trees or grass
+ LLViewerObject* nonflora_objectp = NULL;
+ S32 nonflora_name = -1;
+ S32 nonflora_te_offset = NO_FACE;
+
+ if (name == (S32)GL_NAME_PARCEL_WALL)
{
- return LLPickInfo();
+ gLastHitParcelWall = TRUE;
}
- pickAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent);
- // assume that pickAsync put the results in the back of the mPicks list
- mLastPick = mPicks.back();
- mLastPick.fetchResults();
- mPicks.pop_back();
+ gLastHitHUDIcon = NULL;
- return mLastPick;
+ objectp = gObjectList.getSelectedObject(name);
+ if (objectp)
+ {
+ LLViewerObject* parent = (LLViewerObject*)(objectp->getParent());
+ if (NULL == parent) {
+ // if you are the parent
+ parent = objectp;
+ }
+ if (objectp->mbCanSelect)
+ {
+ te_offset = (te_offset == 16) ? NO_FACE : te_offset;
+
+ // If the hit object isn't a plant, store it as the frontmost non-flora object.
+ LLPCode pcode = objectp->getPCode();
+ if( (LL_PCODE_LEGACY_GRASS != pcode) &&
+ (LL_PCODE_LEGACY_TREE != pcode) &&
+ (LL_PCODE_TREE_NEW != pcode))
+ {
+ nonflora_objectp = objectp;
+ nonflora_name = name;
+ nonflora_te_offset = te_offset;
+ }
+ }
+ else
+ {
+ //llinfos << "Hit object you can't select" << llendl;
+ }
+ }
+ else
+ {
+ // was this name referring to a hud icon?
+ gLastHitHUDIcon = LLHUDIcon::handlePick(name);
+ }
+
+ analyzeHit(
+ mPickPoint.mX, mPickPoint.mY, objectp, te_offset,
+ &gLastHitObjectID, &gLastHitObjectFace, &gLastHitPosGlobal, &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord );
+
+ if (objectp && !gLastHitObjectID.isNull())
+ {
+ gLastHitObjectOffset = gAgent.calcFocusOffset(objectp, mPickPoint.mX, mPickPoint.mY);
+ }
+
+ if( objectp == nonflora_objectp )
+ {
+ gLastHitNonFloraObjectID = gLastHitObjectID;
+ gLastHitNonFloraObjectFace = gLastHitObjectFace;
+ gLastHitNonFloraPosGlobal = gLastHitPosGlobal;
+ gLastHitNonFloraObjectOffset= gLastHitObjectOffset;
+ }
+ else
+ {
+ analyzeHit( mPickPoint.mX, mPickPoint.mY, nonflora_objectp, nonflora_te_offset,
+ &gLastHitNonFloraObjectID, &gLastHitNonFloraObjectFace, &gLastHitNonFloraPosGlobal,
+ &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord);
+
+ if( nonflora_objectp )
+ {
+ gLastHitNonFloraObjectOffset = gAgent.calcFocusOffset(nonflora_objectp, mPickPoint.mX, mPickPoint.mY);
+ }
+ }
+
+ if (mPickCallback)
+ {
+ mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask);
+ }
+
+ gPickFaces = FALSE;
}
-LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
- LLViewerObject *this_object,
- S32 this_face,
- S32* face_hit,
- LLVector3 *intersection,
- LLVector2 *uv,
- LLVector3 *normal,
- LLVector3 *binormal)
+// Performs the GL object/land pick.
+// Stores its results in globals, gHit*
+void LLViewerWindow::hitObjectOrLandGlobalImmediate(S32 x, S32 y_from_bot, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent)
{
- S32 x = mouse_x;
- S32 y = mouse_y;
-
- if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
+ if (gNoRender)
{
- x = getCurrentMouseX();
- y = getCurrentMouseY();
+ return;
}
+
+ hitObjectOrLandGlobalAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent);
+ performPick();
+ if (callback)
+ {
+ callback(x, y_from_bot, gKeyboard->currentMask(TRUE));
+ }
+}
- // HUD coordinates of mouse
- LLVector3 mouse_point_hud = mousePointHUD(x, y);
- LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
- LLVector3 mouse_hud_end = mouse_point_hud + LLVector3(depth, 0, 0);
+LLViewerObject* LLViewerWindow::getObjectUnderCursor(const F32 depth)
+{
+ S32 x = getCurrentMouseX();
+ S32 y = getCurrentMouseY();
- // world coordinates of mouse
LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
- LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
- LLVector3 mouse_world_start = mouse_point_global;
- LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth;
-
+ LLVector3 camera_pos_global = LLViewerCamera::getInstance()->getOrigin();
+ LLVector3 pick_end = camera_pos_global + mouse_direction_global * depth;
+ LLVector3 collision_point;
+ return gPipeline.pickObject(camera_pos_global, pick_end, collision_point);
+}
+
+void LLViewerWindow::analyzeHit(
+ S32 x, // input
+ S32 y_from_bot, // input
+ LLViewerObject* objectp, // input
+ U32 te_offset, // input
+ LLUUID* hit_object_id_p,// output
+ S32* hit_face_p, // output
+ LLVector3d* hit_pos_p, // output
+ BOOL* hit_land, // output
+ F32* hit_u_coord, // output
+ F32* hit_v_coord) // output
+{
+ // Clean up inputs
+ S32 face = -1;
- LLViewerObject* found = NULL;
+ if (te_offset != NO_FACE )
+ {
+ face = te_offset;
+ }
- if (this_object) // check only this object
+ *hit_land = FALSE;
+
+ if (objectp)
{
- if (this_object->isHUDAttachment()) // is a HUD object?
+ if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
{
- if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face,
- face_hit, intersection, uv, normal, binormal))
+ // Hit land
+ *hit_land = TRUE;
+
+ // put global position into land_pos
+ LLVector3d land_pos;
+ if (mousePointOnLandGlobal(x, y_from_bot, &land_pos))
{
- found = this_object;
+ *hit_object_id_p = LLUUID::null;
+ *hit_face_p = -1;
+
+ // Fudge the land focus a little bit above ground.
+ *hit_pos_p = land_pos + LLVector3d(0.f, 0.f, 0.1f);
+ //llinfos << "DEBUG Hit Land " << *hit_pos_p << llendl;
+ return;
}
+ else
+ {
+ //llinfos << "Hit land but couldn't find position" << llendl;
+ // Fall through to "Didn't hit anything"
}
-
- else // is a world object
+ }
+ else
{
- if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face,
- face_hit, intersection, uv, normal, binormal))
+ *hit_object_id_p = objectp->mID;
+ *hit_face_p = face;
+
+ // Hit an object
+ if (objectp->isAvatar())
{
- found = this_object;
+ *hit_pos_p = gAgent.getPosGlobalFromAgent(((LLVOAvatar*)objectp)->mPelvisp->getWorldPosition());
}
+ else if (objectp->mDrawable.notNull())
+ {
+ *hit_pos_p = gAgent.getPosGlobalFromAgent(objectp->getRenderPosition());
}
+ else
+ {
+ // regular object
+ *hit_pos_p = objectp->getPositionGlobal();
}
- else // check ALL objects
+ if (gPickFaces && face > -1 &&
+ objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
+ face < objectp->mDrawable->getNumFaces())
{
- found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end,
- face_hit, intersection, uv, normal, binormal);
-
- if (!found) // if not found in HUD, look in world:
-
+ // render red-blue gradient to get 1/256 precision
+ // then render green grid to get final 1/4096 precision
+ S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]);
+ S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]);
+ const S32 UV_PICK_WIDTH = 41;
+ const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
+ U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
+ S32 pick_face = face;
+ LLFace* facep = objectp->mDrawable->getFace(pick_face);
+ LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
+ glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
+ gPipeline.renderFaceForUVSelect(facep);
+
+ glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
+ U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
+ *hit_u_coord = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
+ *hit_v_coord = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
+ }
+ else
{
- found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end,
- face_hit, intersection, uv, normal, binormal);
+ *hit_u_coord = 0.f;
+ *hit_v_coord = 0.f;
}
+ //llinfos << "DEBUG Hit Object " << *hit_pos_p << llendl;
+ return;
+ }
}
- return found;
+ // Didn't hit anything.
+ *hit_object_id_p = LLUUID::null;
+ *hit_face_p = -1;
+ *hit_pos_p = LLVector3d::zero;
+ *hit_u_coord = 0.f;
+ *hit_v_coord = 0.f;
+ //llinfos << "DEBUG Hit Nothing " << llendl;
}
// Returns unit vector relative to camera
@@ -3632,18 +3884,6 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
return mouse_vector;
}
-LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
-{
- // find screen resolution
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
-
- // remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
- F32 hud_x = -((F32)x - (F32)width/2.f) / height;
- F32 hud_y = ((F32)y - (F32)height/2.f) / height;
-
- return LLVector3(0.f, hud_x, hud_y);
-}
// Returns unit vector relative to camera in camera space
// indicating direction of point on screen x,y
@@ -4009,7 +4249,8 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p
LLHUDText::setDisplayText(FALSE) ;
if (type == SNAPSHOT_TYPE_OBJECT_ID)
{
- gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE);
+ gPickTransparent = FALSE;
+ gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, FALSE);
}
else
{
@@ -4211,8 +4452,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
- gObjectList.generatePickList(*LLViewerCamera::getInstance());
-
for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
{
S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
@@ -4233,7 +4472,9 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor)));
setup3DRender();
setupViewport();
- gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE);
+ BOOL first_time_through = (subimage_x + subimage_y == 0);
+ gPickTransparent = FALSE;
+ gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, !first_time_through);
}
else
{
@@ -4482,6 +4723,27 @@ void LLViewerWindow::setup2DRender()
gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight());
}
+// Could cache the pointer from the last hitObjectOrLand here.
+LLViewerObject *LLViewerWindow::lastObjectHit()
+{
+ return gObjectList.findObject( gLastHitObjectID );
+}
+
+const LLVector3d& LLViewerWindow::lastObjectHitOffset()
+{
+ return gLastHitObjectOffset;
+}
+
+// Could cache the pointer from the last hitObjectOrLand here.
+LLViewerObject *LLViewerWindow::lastNonFloraObjectHit()
+{
+ return gObjectList.findObject( gLastHitNonFloraObjectID );
+}
+
+const LLVector3d& LLViewerWindow::lastNonFloraObjectHitOffset()
+{
+ return gLastHitNonFloraObjectOffset;
+}
void LLViewerWindow::setShowProgress(const BOOL show)
@@ -4904,7 +5166,46 @@ F32 LLViewerWindow::getDisplayAspectRatio() const
void LLViewerWindow::drawPickBuffer() const
{
- mHoverPick.drawPickBuffer();
+ if (mPickBuffer)
+ {
+ gGL.color4f(1,1,1,1);
+ gGL.pushMatrix();
+ LLGLDisable no_blend(GL_BLEND);
+ LLGLDisable no_alpha_test(GL_ALPHA_TEST);
+ LLGLSNoTexture no_texture;
+ glPixelZoom(10.f, 10.f);
+ glRasterPos2f(((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f),
+ ((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f));
+ glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
+ glPixelZoom(1.f, 1.f);
+ gGL.color4fv(LLColor4::white.mV);
+ gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
+ llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
+ FALSE);
+ gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
+ llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f));
+ gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
+ llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f));
+ gGL.translatef(10.f, 10.f, 0.f);
+ gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f),
+ llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]),
+ FALSE);
+ gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX)* 10.f),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH + mPickOffset.mY + 1) * 10.f),
+ llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX + 1) * 10.f),
+ llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH + mPickOffset.mY) * 10.f),
+ FALSE);
+ gGL.popMatrix();
+ gGL.flush();
+ }
}
void LLViewerWindow::calcDisplayScale()
@@ -5093,342 +5394,3 @@ void* LLBottomPanel::createToolBar(void* data)
gToolBar = new LLToolBar();
return gToolBar;
}
-
-//
-// LLPickInfo
-//
-LLPickInfo::LLPickInfo()
- : mKeyMask(MASK_NONE),
- mPickCallback(NULL),
- mPickType(PICK_INVALID),
- mWantSurfaceInfo(FALSE),
- mObjectFace(-1),
- mUVCoords(-1.f, -1.f),
- mSTCoords(-1.f, -1.f),
- mXYCoords(-1, -1),
- mIntersection(),
- mNormal(),
- mBinormal(),
- mHUDIcon(NULL),
- mPickTransparent(FALSE)
-{
-}
-
-LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,
- const LLRect& screen_region,
- MASK keyboard_mask,
- BOOL pick_transparent,
- BOOL pick_uv_coords,
- void (*pick_callback)(const LLPickInfo& pick_info))
- : mMousePt(mouse_pos),
- mScreenRegion(screen_region),
- mKeyMask(keyboard_mask),
- mPickCallback(pick_callback),
- mPickType(PICK_INVALID),
- mWantSurfaceInfo(pick_uv_coords),
- mObjectFace(-1),
- mUVCoords(-1.f, -1.f),
- mSTCoords(-1.f, -1.f),
- mXYCoords(-1, -1),
- mNormal(),
- mBinormal(),
- mHUDIcon(NULL),
- mPickTransparent(pick_transparent)
-{
-}
-
-LLPickInfo::~LLPickInfo()
-{
-}
-
-void LLPickInfo::fetchResults()
-{
- // read back colors and depth values from buffer
- glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
- glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_DEPTH_COMPONENT, GL_FLOAT, mPickDepthBuffer );
-
- // find pick region that is fully onscreen
- LLCoordGL scaled_pick_point;;
- scaled_pick_point.mX = llclamp(llround((F32)mMousePt.mX * gViewerWindow->getDisplayScale().mV[VX]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayWidth() - PICK_HALF_WIDTH);
- scaled_pick_point.mY = llclamp(llround((F32)mMousePt.mY * gViewerWindow->getDisplayScale().mV[VY]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayHeight() - PICK_HALF_WIDTH);
- S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH;
- S32 pick_id = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
- F32 depth = mPickDepthBuffer[pixel_index];
-
- S32 x_offset = mMousePt.mX - llround((F32)scaled_pick_point.mX / gViewerWindow->getDisplayScale().mV[VX]);
- S32 y_offset = mMousePt.mY - llround((F32)scaled_pick_point.mY / gViewerWindow->getDisplayScale().mV[VY]);
-
- mPickPt = mMousePt;
-
- // we hit nothing, scan surrounding pixels for something useful
- if (!pick_id)
- {
- S32 closest_distance = 10000;
- //S32 closest_pick_name = 0;
- for (S32 col = 0; col < PICK_DIAMETER; col++)
- {
- for (S32 row = 0; row < PICK_DIAMETER; row++)
- {
- S32 distance_squared = (llabs(col - x_offset - PICK_HALF_WIDTH) * llabs(col - x_offset - PICK_HALF_WIDTH)) + (llabs(row - y_offset - PICK_HALF_WIDTH) * llabs(row - y_offset - PICK_HALF_WIDTH));
- pixel_index = row * PICK_DIAMETER + col;
- S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
- if (test_name && distance_squared < closest_distance)
- {
- closest_distance = distance_squared;
- pick_id = test_name;
- depth = mPickDepthBuffer[pixel_index];
- mPickPt.mX = mMousePt.mX + (col - PICK_HALF_WIDTH);
- mPickPt.mY = mMousePt.mY + (row - PICK_HALF_WIDTH);
- }
- }
- }
- }
-
- U32 te_offset = ((U32)pick_id >> 20);
- pick_id &= 0x000fffff;
-
- //unproject relative clicked coordinate from window coordinate using GL
- GLint viewport[4];
- GLdouble modelview[16];
- GLdouble projection[16];
- GLfloat winX, winY;
- GLdouble posX, posY, posZ;
-
- LLViewerObject* objectp = gObjectList.getSelectedObject(pick_id);
-
- if (pick_id == (S32)GL_NAME_PARCEL_WALL)
- {
- mPickType = PICK_PARCEL_WALL;
- }
- else if (objectp)
- {
- if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
- {
- // Hit land
- mPickType = PICK_LAND;
- mObjectID.setNull(); // land has no id
-
- // put global position into land_pos
- LLVector3d land_pos;
- if (gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos))
- {
- // Fudge the land focus a little bit above ground.
- mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
- }
- }
- else
- {
- if(isFlora(objectp))
- {
- mPickType = PICK_FLORA;
- }
- else
- {
- mPickType = PICK_OBJECT;
- }
- mObjectOffset = gAgent.calcFocusOffset(objectp, mPickPt.mX, mPickPt.mY);
- mObjectID = objectp->mID;
- mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
-
- glh::matrix4f newModel((F32*)LLViewerCamera::getInstance()->getModelview().mMatrix);
-
- for(U32 i = 0; i < 16; ++i)
- {
- modelview[i] = newModel.m[i];
- projection[i] = LLViewerCamera::getInstance()->getProjection().mMatrix[i/4][i%4];
- }
- glGetIntegerv( GL_VIEWPORT, viewport );
-
- winX = ((F32)mPickPt.mX) * gViewerWindow->getDisplayScale().mV[VX];
- winY = ((F32)mPickPt.mY) * gViewerWindow->getDisplayScale().mV[VY];
-
- gluUnProject( winX, winY, depth, modelview, projection, viewport, &posX, &posY, &posZ);
-
- mPosGlobal = gAgent.getPosGlobalFromAgent(LLVector3(posX, posY, posZ));
-
- if (mWantSurfaceInfo)
- {
- getSurfaceInfo();
- }
- }
- }
- else
- {
- // was this name referring to a hud icon?
- mHUDIcon = LLHUDIcon::handlePick(pick_id);
- if (mHUDIcon)
- {
- mPickType = PICK_ICON;
- mPosGlobal = mHUDIcon->getPositionGlobal();
- }
- }
-
- if (mPickCallback)
- {
- mPickCallback(*this);
- }
-}
-
-LLPointer<LLViewerObject> LLPickInfo::getObject() const
-{
- return gObjectList.findObject( mObjectID );
-}
-
-void LLPickInfo::updateXYCoords()
-{
- const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
- LLPointer<LLViewerImage> imagep = gImageList.getImage(tep->getID());
- if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
- {
- LLCoordGL coords;
-
- coords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
- coords.mY = llround(mUVCoords.mV[VY] * (F32)imagep->getHeight());
-
- gViewerWindow->getWindow()->convertCoords(coords, &mXYCoords);
- }
-}
-
-void LLPickInfo::drawPickBuffer() const
-{
- if (mPickBuffer)
- {
- gGL.pushMatrix();
- LLGLDisable no_blend(GL_BLEND);
- LLGLDisable no_alpha_test(GL_ALPHA_TEST);
- LLGLSNoTexture no_texture;
- glPixelZoom(10.f, 10.f);
- LLVector2 display_scale = gViewerWindow->getDisplayScale();
- glRasterPos2f(((F32)mMousePt.mX * display_scale.mV[VX] + 10.f),
- ((F32)mMousePt.mY * display_scale.mV[VY] + 10.f));
- glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
- glPixelZoom(1.f, 1.f);
- gGL.color4fv(LLColor4::white.mV);
- gl_rect_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
- FALSE);
- gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + 10.f),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f));
- gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + 10.f));
- gGL.translatef(10.f, 10.f, 0.f);
- gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]),
- llround((F32)mPickPt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f),
- llround((F32)mPickPt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f),
- llround((F32)mPickPt.mY * display_scale.mV[VY]),
- FALSE);
- gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]),
- llround((F32)mPickPt.mY * display_scale.mV[VY] + 10.f),
- llround((F32)mPickPt.mX * display_scale.mV[VX] + 10.f),
- llround((F32)mPickPt.mY * display_scale.mV[VY]),
- FALSE);
- gGL.popMatrix();
- }
-}
-
-void LLPickInfo::getSurfaceInfo()
-{
- // set values to uninitialized - this is what we return if no intersection is found
- mObjectFace = -1;
- mUVCoords = LLVector2(-1, -1);
- mSTCoords = LLVector2(-1, -1);
- mXYCoords = LLCoordScreen(-1, -1);
- mIntersection = LLVector3(0,0,0);
- mNormal = LLVector3(0,0,0);
- mBinormal = LLVector3(0,0,0);
-
- LLViewerObject* objectp = getObject();
-
- if (objectp)
- {
- if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f,
- objectp, -1,
- &mObjectFace,
- &mIntersection,
- &mSTCoords,
- &mNormal,
- &mBinormal))
- {
- // if we succeeded with the intersect above, compute the texture coordinates:
-
- if (objectp->mDrawable.notNull())
- {
- LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
-
- mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal);
- }
-
- // and XY coords:
- updateXYCoords();
-
- }
- }
-}
-
-
-/* code to get UV via a special UV render - removed in lieu of raycast method
-LLVector2 LLPickInfo::pickUV()
-{
- LLVector2 result(-1.f, -1.f);
-
- LLViewerObject* objectp = getObject();
- if (!objectp)
- {
- return result;
- }
-
- if (mObjectFace > -1 &&
- objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
- mObjectFace < objectp->mDrawable->getNumFaces())
- {
- S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]);
- S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]);
- const S32 UV_PICK_WIDTH = 5;
- const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
- U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
- LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
- if (facep)
- {
- LLGLState scissor_state(GL_SCISSOR_TEST);
- scissor_state.enable();
- LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
- //glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
- glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
-
- glClear(GL_DEPTH_BUFFER_BIT);
-
- facep->renderSelectedUV();
-
- glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
- U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
-
- result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
- result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
- }
- }
-
- return result;
-} */
-
-
-//static
-bool LLPickInfo::isFlora(LLViewerObject* object)
-{
- if (!object) return false;
-
- LLPCode pcode = object->getPCode();
-
- if( (LL_PCODE_LEGACY_GRASS == pcode)
- || (LL_PCODE_LEGACY_TREE == pcode)
- || (LL_PCODE_TREE_NEW == pcode))
- {
- return true;
- }
- return false;
-}