void LLViewerCamera::setPerspective(BOOL for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, BOOL limit_select_distance, F32 z_near, F32 z_far) { F32 fov_y, aspect; fov_y = RAD_TO_DEG * getView(); BOOL z_default_near, z_default_far = FALSE; if (z_far <= 0) { z_default_far = TRUE; z_far = getFar(); } if (z_near <= 0) { z_default_near = TRUE; z_near = getNear(); } aspect = getAspect(); // Load camera view matrix glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glh::matrix4f proj_mat; if (for_selection) { // make a tiny little viewport // anything drawn into this viewport will be "selected" GLint viewport[4]; viewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; viewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; viewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); viewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); proj_mat = gl_pick_matrix(x+width/2.f, y_from_bot+height/2.f, (GLfloat) width, (GLfloat) height, viewport); if (limit_select_distance) { // ...select distance from control z_far = gSavedSettings.getF32("MaxSelectDistance"); } else { z_far = gAgent.mDrawDistance; } } else { // Only override the far clip if it's not passed in explicitly. if (z_default_far) { z_far = MAX_FAR_CLIP; } glViewport(x, y_from_bot, width, height); gGLViewport[0] = x; gGLViewport[1] = y_from_bot; gGLViewport[2] = width; gGLViewport[3] = height; } if (mZoomFactor > 1.f) { float offset = mZoomFactor - 1.f; int pos_y = mZoomSubregion / llceil(mZoomFactor); int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor)); glh::matrix4f translate; translate.set_translate(glh::vec3f(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f)); glh::matrix4f scale; scale.set_scale(glh::vec3f(mZoomFactor, mZoomFactor, 1.f)); proj_mat = scale*proj_mat; proj_mat = translate*proj_mat; } calcProjection(z_far); // Update the projection matrix cache proj_mat *= gl_perspective(fov_y,aspect,z_near,z_far); glLoadMatrixf(proj_mat.m); for (U32 i = 0; i < 16; i++) { gGLProjection[i] = proj_mat.m[i]; } glMatrixMode( GL_MODELVIEW ); glh::matrix4f modelview((GLfloat*) OGL_TO_CFR_ROTATION); GLfloat ogl_matrix[16]; getOpenGLTransform(ogl_matrix); modelview *= glh::matrix4f(ogl_matrix); glLoadMatrixf(modelview.m); if (for_selection && (width > 1 || height > 1)) { // NB: as of this writing, i believe the code below is broken (doesn't take into account the world view, assumes entire window) // however, it is also unused (the GL matricies are used for selection, (see LLCamera::sphereInFrustum())) and so i'm not // comfortable hacking on it. calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f, (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f); } // if not picking and not doing a snapshot, cache various GL matrices if (!for_selection && mZoomFactor == 1.f) { // Save GL matrices for access elsewhere in code, especially project_world_to_screen //glGetDoublev(GL_MODELVIEW_MATRIX, gGLModelView); for (U32 i = 0; i < 16; i++) { gGLModelView[i] = modelview.m[i]; } } updateFrustumPlanes(*this); /*if (gSavedSettings.getBOOL("CameraOffset")) { glMatrixMode(GL_PROJECTION); glTranslatef(0,0,-50); glRotatef(20.0,1,0,0); glMatrixMode(GL_MODELVIEW); }*/ }
void LLViewerCamera::setPerspective(BOOL for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, BOOL limit_select_distance, F32 z_near, F32 z_far) { F32 fov_y, aspect; fov_y = RAD_TO_DEG * getView(); BOOL z_default_far = FALSE; if (z_far <= 0) { z_default_far = TRUE; z_far = getFar(); } if (z_near <= 0) { z_near = getNear(); } aspect = getAspect(); // Load camera view matrix gGL.matrixMode( LLRender::MM_PROJECTION ); gGL.loadIdentity(); LLMatrix4a proj_mat; proj_mat.setIdentity(); if (for_selection) { // make a tiny little viewport // anything drawn into this viewport will be "selected" const LLRect& rect = gViewerWindow->getWorldViewRectRaw(); const F32 scale_x = rect.getWidth() / F32(width); const F32 scale_y = rect.getHeight() / F32(height); const F32 trans_x = scale_x + (2.f * (rect.mLeft - x)) / F32(width) - 1.f; const F32 trans_y = scale_y + (2.f * (rect.mBottom - y_from_bot)) / F32(height) - 1.f; //Generate a pick matrix proj_mat.applyScale_affine(scale_x, scale_y, 1.f); proj_mat.setTranslate_affine(LLVector3(trans_x, trans_y, 0.f)); if (limit_select_distance) { // ...select distance from control // z_far = gSavedSettings.getF32("MaxSelectDistance"); // [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Added: RLVa-1.2.0e z_far = (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) ? gSavedSettings.getF32("MaxSelectDistance") : 1.5; // [/RLVa:KB] } else { z_far = gAgentCamera.mDrawDistance; } } else { // Only override the far clip if it's not passed in explicitly. if (z_default_far) { z_far = MAX_FAR_CLIP; } glViewport(x, y_from_bot, width, height); gGLViewport[0] = x; gGLViewport[1] = y_from_bot; gGLViewport[2] = width; gGLViewport[3] = height; } if (mZoomFactor > 1.f) { float offset = mZoomFactor - 1.f; int pos_y = mZoomSubregion / llceil(mZoomFactor); int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor)); proj_mat.applyTranslation_affine(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f); proj_mat.applyScale_affine(mZoomFactor,mZoomFactor,1.f); } calcProjection(z_far); // Update the projection matrix cache proj_mat.mul(gGL.genPersp(fov_y,aspect,z_near,z_far)); gGL.loadMatrix(proj_mat); gGLProjection = proj_mat; gGL.matrixMode(LLRender::MM_MODELVIEW ); LLMatrix4a ogl_matrix; getOpenGLTransform(ogl_matrix.getF32ptr()); LLMatrix4a modelview; modelview.setMul(OGL_TO_CFR_ROTATION, ogl_matrix); gGL.loadMatrix(modelview); if (for_selection && (width > 1 || height > 1)) { // NB: as of this writing, i believe the code below is broken (doesn't take into account the world view, assumes entire window) // however, it is also unused (the GL matricies are used for selection, (see LLCamera::sphereInFrustum())) and so i'm not // comfortable hacking on it. calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f, (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f); } // if not picking and not doing a snapshot, cache various GL matrices if (!for_selection && mZoomFactor == 1.f) { // Save GL matrices for access elsewhere in code, especially project_world_to_screen //glGetDoublev(GL_MODELVIEW_MATRIX, gGLModelView); glh_set_current_modelview(modelview); } updateFrustumPlanes(*this); /*if (gSavedSettings.getBOOL("CameraOffset")) { gGL.matrixMode(LLRender::MM_PROJECTION); gGL.translatef(0,0,-50); gGL.rotatef(20.0,1,0,0); gGL.matrixMode(LLRender::MM_MODELVIEW); }*/ }