diff options
Diffstat (limited to 'indra/newview/llviewerwindow.cpp')
-rw-r--r-- | indra/newview/llviewerwindow.cpp | 994 |
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; -} |