void LLViewerCamera::calcProjection(const F32 far_distance) const { F32 fov_y, z_far, z_near, aspect, f; fov_y = getView(); z_far = far_distance; z_near = getNear(); aspect = getAspect(); f = 1/tan(fov_y*0.5f); mProjectionMatrix.setZero(); mProjectionMatrix.mMatrix[0][0] = f/aspect; mProjectionMatrix.mMatrix[1][1] = f; mProjectionMatrix.mMatrix[2][2] = (z_far + z_near)/(z_near - z_far); mProjectionMatrix.mMatrix[3][2] = (2*z_far*z_near)/(z_near - z_far); mProjectionMatrix.mMatrix[2][3] = -1; }
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::calcProjection(const F32 far_distance) const { mProjectionMatrix = gGL.genPersp( getView()*RAD_TO_DEG, getAspect(), getNear(), far_distance ); }
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); }*/ }
void Frustum::generateFrustumPlanes( Camera* camera, Plane* frustum ) { // Generate planes float nearHeight = 2 * tan( getFOV() / 2 ) * getNear(); float nearWidth = nearHeight * getAspect(); //float farHeight = 2 * tan( getFOV() / 2 ) * getFar(); //float farWidth = farHeight * getAspect(); Vector3 fc, nc, tmp; Vector3 ynh, xnw, X, Y, Z; Z = Vector3( camera->getCenterOfProjection() ); Z.sub( Z, camera->getLookAtPoint() ); Z.normalize(); X.cross( camera->getUp(), Z ); X.normalize(); Y.cross( Z, X ); ynh = Vector3( Y ); ynh.scale( nearHeight / 2 ); xnw = Vector3( X ); xnw.scale( nearWidth / 2 ); tmp = Vector3( Z ); tmp.scale( getNear() ); nc = Vector3( camera->getCenterOfProjection() ); nc.sub( nc, tmp ); tmp = Vector3( Z ); tmp.scale( getFar() ); fc = Vector3( camera->getCenterOfProjection() ); fc.sub( fc, tmp ); Vector3 aux, normal; frustum[ NEAR ].setNormal( Z.getX(), Z.getY(), Z.getZ() ); frustum[ NEAR ].setPoint( nc ); frustum[ FAR ].setNormal( -Z.getX(), -Z.getY(), -Z.getZ() ); frustum[ FAR ].setPoint( fc ); aux = Vector3( nc ); aux.add( aux, ynh ); frustum[ TOP ].setPoint( aux ); aux.sub( aux, camera->getCenterOfProjection() ); aux.normalize(); normal.cross( aux, X ); frustum[ TOP ].setNormal( normal.getX(), normal.getY(), normal.getZ() ); aux = Vector3( nc ); aux.sub( aux, ynh ); frustum[ BOTTOM ].setPoint( aux ); aux.sub( aux, camera->getCenterOfProjection() ); aux.normalize(); normal.cross( X, aux ); frustum[ BOTTOM ].setNormal( normal.getX(), normal.getY(), normal.getZ() ); aux = Vector3( nc ); aux.sub( aux, xnw ); frustum[ LEFT ].setPoint( aux ); aux.sub( aux, camera->getCenterOfProjection() ); aux.normalize(); normal.cross( aux, Y ); frustum[ LEFT ].setNormal( normal.getX(), normal.getY(), normal.getZ() ); aux = Vector3( nc ); aux.add( aux, xnw ); frustum[ RIGHT ].setPoint( aux ); aux.sub( aux, camera->getCenterOfProjection() ); aux.normalize(); normal.cross( Y, aux ); frustum[ RIGHT ].setNormal( normal.getX(), normal.getY(), normal.getZ() ); }