123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836 |
- /**
- * @file llviewercamera.cpp
- * @brief LLViewerCamera class implementation
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llviewercamera.h"
- #include "llgl.h"
- #include "llmatrix4a.h"
- #include "llagent.h"
- #include "lldrawable.h"
- #include "llface.h"
- #include "llpipeline.h"
- //MK
- #include "mkrlinterface.h"
- //mk
- #include "lltoolmgr.h"
- #include "llviewercontrol.h"
- #include "llviewerdisplay.h" // For gCubeSnapshot
- #include "llviewerjoystick.h"
- #include "llviewerobjectlist.h"
- #include "llviewerregion.h"
- #include "llviewerwindow.h"
- #include "llvovolume.h"
- #include "llworld.h"
- LLViewerCamera gViewerCamera;
- // Static members
- LLStat LLViewerCamera::sVelocityStat;
- LLStat LLViewerCamera::sAngularVelocityStat;
- S32 LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- LLViewerCamera::LLViewerCamera()
- : LLCamera()
- {
- calcProjection(getFar());
- mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
- mPrevCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
- mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
- mPixelMeterRatio = 0.f;
- mScreenPixelArea = 0;
- mZoomFactor = 1.f;
- mZoomSubregion = 1;
- mAverageSpeed = 0.f;
- mAverageAngularSpeed = 0.f;
- }
- //static
- void LLViewerCamera::initClass()
- {
- LLControlVariable* ctrlp = gSavedSettings.getControl("CameraAngle");
- if (!ctrlp)
- {
- llwarns << "Missing CameraAngle debug setting." << llendl;
- return;
- }
- ctrlp->getSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle,
- _2));
- llinfos << "Viewer camera initialized." << llendl;
- }
- //static
- void LLViewerCamera::updateCameraAngle(const LLSD& value)
- {
- gViewerCamera.setDefaultFOV(value.asReal());
- }
- void LLViewerCamera::updateCameraLocation(const LLVector3& center,
- const LLVector3& up_direction,
- const LLVector3& point_of_interest)
- {
- // Do not update if we are in build mode AND avatar did not move
- if (gToolMgr.inBuildMode() &&
- !LLViewerJoystick::getInstance()->getCameraNeedsUpdate())
- {
- return;
- }
- LLVector3 last_position;
- LLVector3 last_axis;
- last_position = getOrigin();
- last_axis = getAtAxis();
- mLastPointOfInterest = point_of_interest;
- // Constrain to max distance from avatar
- LLViewerRegion* regionp = gWorld.getRegionFromPosAgent(getOrigin());
- if (!regionp)
- {
- regionp = gAgent.getRegion();
- }
- F32 water_height = regionp ? regionp->getWaterHeight() : 0.f;
- LLVector3 origin = center;
- if (origin.mV[2] > water_height)
- {
- origin.mV[2] = llmax(origin.mV[2], water_height + 0.20f);
- }
- else
- {
- origin.mV[2] = llmin(origin.mV[2], water_height - 0.20f);
- }
- setOriginAndLookAt(origin, up_direction, point_of_interest);
- mVelocityDir = center - last_position;
- F32 dpos = mVelocityDir.normalize();
- LLQuaternion rotation;
- rotation.shortestArc(last_axis, getAtAxis());
- F32 x, y, z;
- F32 drot;
- rotation.getAngleAxis(&drot, &x, &y, &z);
- sVelocityStat.addValue(dpos);
- sAngularVelocityStat.addValue(drot);
- mAverageSpeed = sVelocityStat.getMeanPerSec();
- mAverageAngularSpeed = sAngularVelocityStat.getMeanPerSec();
- mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect()));
- // update pixel meter ratio using default fov, not modified one
- mPixelMeterRatio = getViewHeightInPixels() / (2.f * tanf(mCameraFOVDefault * 0.5));
- // update screen pixel area
- mScreenPixelArea = (S32)((F32)getViewHeightInPixels() *
- ((F32)getViewHeightInPixels() * getAspect()));
- }
- const LLMatrix4& LLViewerCamera::getProjection() const
- {
- calcProjection(getFar());
- return mProjectionMatrix;
- }
- const LLMatrix4& LLViewerCamera::getModelview() const
- {
- LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
- getMatrixToLocal(mModelviewMatrix);
- mModelviewMatrix *= cfr;
- return mModelviewMatrix;
- }
- void LLViewerCamera::calcProjection(F32 far_distance) const
- {
- F32 fov_y = getView();
- F32 z_far = far_distance;
- F32 z_near = getNear();
- F32 aspect = getAspect();
- F32 f = 1.f / tanf(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;
- }
- //static
- void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, bool ortho,
- bool zflip, bool no_hacks)
- {
- LLVector3 frust[8];
- LLRect view_port(gGLViewport[0], gGLViewport[1] + gGLViewport[3],
- gGLViewport[0] + gGLViewport[2], gGLViewport[1]);
- if (no_hacks)
- {
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 0.f),
- gGLModelView, gGLProjection, view_port, frust[0]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 0.f),
- gGLModelView, gGLProjection, view_port, frust[1]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mTop, 0.f),
- gGLModelView, gGLProjection, view_port, frust[2]);
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 0.f),
- gGLModelView, gGLProjection, view_port, frust[3]);
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 1.f),
- gGLModelView, gGLProjection, view_port, frust[4]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 1.f),
- gGLModelView, gGLProjection, view_port, frust[5]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mTop, 1.f),
- gGLModelView, gGLProjection, view_port, frust[6]);
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 1.f),
- gGLModelView, gGLProjection, view_port, frust[7]);
- }
- else if (zflip)
- {
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 0.f),
- gGLModelView, gGLProjection, view_port, frust[0]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mTop, 0.f),
- gGLModelView, gGLProjection, view_port, frust[1]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 0.f),
- gGLModelView, gGLProjection, view_port, frust[2]);
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 0.f),
- gGLModelView, gGLProjection, view_port, frust[3]);
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 1.f),
- gGLModelView, gGLProjection, view_port, frust[4]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mTop, 1.f),
- gGLModelView, gGLProjection, view_port, frust[5]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 1.f),
- gGLModelView, gGLProjection, view_port, frust[6]);
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 1.f),
- gGLModelView, gGLProjection, view_port, frust[7]);
- for (U32 i = 0; i < 4; ++i)
- {
- frust[i + 4] = frust[i + 4] - frust[i];
- frust[i + 4].normalize();
- frust[i + 4] = frust[i] + frust[i + 4] * camera.getFar();
- }
- }
- else
- {
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 0.f),
- gGLModelView, gGLProjection, view_port, frust[0]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 0.f),
- gGLModelView, gGLProjection, view_port, frust[1]);
- gGL.unprojectf(LLVector3(view_port.mRight, view_port.mTop, 0.f),
- gGLModelView, gGLProjection, view_port, frust[2]);
- gGL.unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 0.f),
- gGLModelView, gGLProjection, view_port, frust[3]);
- if (ortho)
- {
- LLVector3 far_shift = camera.getAtAxis() * camera.getFar() * 2.f;
- for (U32 i = 0; i < 4; ++i)
- {
- frust[i + 4] = frust[i] + far_shift;
- }
- }
- else
- {
- for (U32 i = 0; i < 4; ++i)
- {
- LLVector3 vec = frust[i] - camera.getOrigin();
- vec.normalize();
- frust[i + 4] = camera.getOrigin() + vec * camera.getFar();
- }
- }
- }
- camera.calcAgentFrustumPlanes(frust);
- }
- void LLViewerCamera::setPerspective(bool for_selection, S32 x, S32 y_from_bot,
- S32 width, S32 height, bool limit_sel_dist,
- F32 z_near, F32 z_far)
- {
- F32 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();
- }
- F32 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 = gViewerWindowp->getWindowRect();
- F32 scale_x = rect.getWidth() / F32(width);
- F32 scale_y = rect.getHeight() / F32(height);
- F32 trans_x = scale_x + 2.f * (rect.mLeft - x) / (F32)width - 1.f;
- F32 trans_y = scale_y + 2.f * (rect.mBottom - y_from_bot) /
- (F32)height - 1.f;
- // Generate a pick matrix
- proj_mat.applyScaleAffine(scale_x, scale_y, 1.f);
- proj_mat.setTranslateAffine(LLVector3(trans_x, trans_y, 0.f));
- if (limit_sel_dist)
- {
- // Select distance from control
- static LLCachedControl<F32> max_select_distance(gSavedSettings,
- "MaxSelectDistance");
- z_far = llclamp((F32)max_select_distance, 32.f, 512.f);
- }
- 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)
- {
- F32 offset = mZoomFactor - 1.f;
- S32 pos_y = mZoomSubregion / llceil(mZoomFactor);
- S32 pos_x = mZoomSubregion - pos_y * llceil(mZoomFactor);
- proj_mat.applyTranslationAffine(offset - (F32)pos_x * 2.f,
- offset - (F32)pos_y * 2.f, 0.f);
- proj_mat.applyScaleAffine(mZoomFactor, mZoomFactor, 1.f);
- }
- calcProjection(z_far); // Update the projection matrix cache
- proj_mat.mul(gl_perspective(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_ROT4A, ogl_matrix);
- gGL.loadMatrix(modelview);
- if (for_selection && (width > 1 || height > 1))
- {
- F32 wwidth = (F32)gViewerWindowp->getWindowWidth();
- F32 wheight = (F32)gViewerWindowp->getWindowHeight();
- calculateFrustumPlanesFromWindow((F32)(x - width / 2) / wwidth - 0.5f,
- (F32)(y_from_bot - height / 2) / wheight - 0.5f,
- (F32)(x + width / 2) / wwidth - 0.5f,
- (F32)(y_from_bot + height / 2) / wheight - 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
- gGLModelView = modelview;
- }
- updateFrustumPlanes(*this);
- }
- // Uses the last GL matrices set in set_perspective to project a point from
- // screen coordinates to the agent's region.
- void LLViewerCamera::projectScreenToPosAgent(S32 screen_x, S32 screen_y,
- LLVector3* pos_agent) const
- {
- gGL.unprojectf(LLVector3(screen_x, screen_y, 0.f),
- gGLModelView, gGLProjection,
- LLRect(gGLViewport[0], gGLViewport[1] + gGLViewport[3],
- gGLViewport[0] + gGLViewport[2], gGLViewport[1]),
- *pos_agent);
- }
- // Uses the last GL matrices set in set_perspective to project a point from the
- // agent's region space to screen coordinates. Returns true if point in within
- // the current window.
- bool LLViewerCamera::projectPosAgentToScreen(const LLVector3& pos_agent,
- LLCoordGL& out_point,
- bool clamp) const
- {
- bool in_front = true;
- LLVector3 dir_to_point = pos_agent - getOrigin();
- dir_to_point /= dir_to_point.length();
- if (dir_to_point * getAtAxis() < 0.f)
- {
- if (clamp)
- {
- return false;
- }
- else
- {
- in_front = false;
- }
- }
- LLVector3 window_coordinates;
- if (gGL.projectf(pos_agent, gGLModelView, gGLProjection,
- LLRect(gGLViewport[0], gGLViewport[1] + gGLViewport[3],
- gGLViewport[0] + gGLViewport[2], gGLViewport[1]),
- window_coordinates))
- {
- F32& x = window_coordinates.mV[VX];
- F32& y = window_coordinates.mV[VY];
- // convert screen coordinates to virtual UI coordinates
- x /= gViewerWindowp->getDisplayScale().mV[VX];
- y /= gViewerWindowp->getDisplayScale().mV[VY];
- // should now have the x,y coords of grab_point in screen space
- const LLRect& window_rect = gViewerWindowp->getWindowRect();
- // ...sanity check
- S32 int_x = lltrunc(x);
- S32 int_y = lltrunc(y);
- bool valid = true;
- if (clamp)
- {
- if (int_x < window_rect.mLeft)
- {
- out_point.mX = window_rect.mLeft;
- valid = false;
- }
- else if (int_x > window_rect.mRight)
- {
- out_point.mX = window_rect.mRight;
- valid = false;
- }
- else
- {
- out_point.mX = int_x;
- }
- if (int_y < window_rect.mBottom)
- {
- out_point.mY = window_rect.mBottom;
- valid = false;
- }
- else if (int_y > window_rect.mTop)
- {
- out_point.mY = window_rect.mTop;
- valid = false;
- }
- else
- {
- out_point.mY = int_y;
- }
- return valid;
- }
- else
- {
- out_point.mX = int_x;
- out_point.mY = int_y;
- if (int_x < window_rect.mLeft)
- {
- valid = false;
- }
- else if (int_x > window_rect.mRight)
- {
- valid = false;
- }
- if (int_y < window_rect.mBottom)
- {
- valid = false;
- }
- else if (int_y > window_rect.mTop)
- {
- valid = false;
- }
- return in_front && valid;
- }
- }
- else
- {
- return false;
- }
- }
- // Uses the last GL matrices set in set_perspective to project a point from the
- // agent's region space to the nearest edge in screen coordinates. Returns true
- // if the projection succeeded.
- bool LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3& pos_agent,
- LLCoordGL& out_point) const
- {
- LLVector3 dir_to_point = pos_agent - getOrigin();
- dir_to_point /= dir_to_point.length();
- bool in_front = true;
- if (dir_to_point * getAtAxis() < 0.f)
- {
- in_front = false;
- }
- LLVector3 window_coordinates;
- if (gGL.projectf(pos_agent, gGLModelView, gGLProjection,
- LLRect(gGLViewport[0], gGLViewport[1] + gGLViewport[3],
- gGLViewport[0] + gGLViewport[2], gGLViewport[1]),
- window_coordinates))
- {
- F32& x = window_coordinates.mV[VX];
- F32& y = window_coordinates.mV[VY];
- x /= gViewerWindowp->getDisplayScale().mV[VX];
- y /= gViewerWindowp->getDisplayScale().mV[VY];
- // should now have the x,y coords of grab_point in screen space
- const LLRect& window_rect = gViewerWindowp->getVirtualWindowRect();
- // ...sanity check
- S32 int_x = lltrunc(x);
- S32 int_y = lltrunc(y);
- // find the center
- GLdouble center_x = (GLdouble)(0.5f * (window_rect.mLeft + window_rect.mRight));
- GLdouble center_y = (GLdouble)(0.5f * (window_rect.mBottom + window_rect.mTop));
- if (x == center_x && y == center_y)
- {
- // can't project to edge from exact center
- return false;
- }
- // find the line from center to local
- GLdouble line_x = x - center_x;
- GLdouble line_y = y - center_y;
- int_x = lltrunc(center_x);
- int_y = lltrunc(center_y);
- if (0.f == line_x)
- {
- // the slope of the line is undefined
- if (line_y > 0.f)
- {
- int_y = window_rect.mTop;
- }
- else
- {
- int_y = window_rect.mBottom;
- }
- }
- else if (0 == window_rect.getWidth())
- {
- // the diagonal slope of the view is undefined
- if (y < window_rect.mBottom)
- {
- int_y = window_rect.mBottom;
- }
- else if (y > window_rect.mTop)
- {
- int_y = window_rect.mTop;
- }
- }
- else
- {
- F32 line_slope = (F32)(line_y / line_x);
- F32 rect_slope = (F32)window_rect.getHeight() / (F32)window_rect.getWidth();
- if (fabs(line_slope) > rect_slope)
- {
- if (line_y < 0.f)
- {
- // bottom
- int_y = window_rect.mBottom;
- }
- else
- {
- // top
- int_y = window_rect.mTop;
- }
- int_x = lltrunc(((GLdouble)int_y - center_y) / line_slope + center_x);
- }
- else if (fabs(line_slope) < rect_slope)
- {
- if (line_x < 0.f)
- {
- // left
- int_x = window_rect.mLeft;
- }
- else
- {
- // right
- int_x = window_rect.mRight;
- }
- int_y = lltrunc(((GLdouble)int_x - center_x) * line_slope + center_y);
- }
- else
- {
- // exactly parallel ==> push to the corners
- if (line_x > 0.f)
- {
- int_x = window_rect.mRight;
- }
- else
- {
- int_x = window_rect.mLeft;
- }
- if (line_y > 0.0f)
- {
- int_y = window_rect.mTop;
- }
- else
- {
- int_y = window_rect.mBottom;
- }
- }
- }
- if (!in_front)
- {
- int_x = window_rect.mLeft + window_rect.mRight - int_x;
- int_y = window_rect.mBottom + window_rect.mTop - int_y;
- }
- out_point.mX = int_x;
- out_point.mY = int_y;
- return true;
- }
- return false;
- }
- void LLViewerCamera::getPixelVectors(const LLVector3& pos_agent, LLVector3& up,
- LLVector3& right)
- {
- LLVector3 to_vec = pos_agent - getOrigin();
- F32 at_dist = to_vec * getAtAxis();
- F32 height_meters = at_dist * tanf(getView() * 0.5f);
- F32 height_pixels = getViewHeightInPixels() * 0.5f;
- F32 pixel_aspect = gWindowp->getPixelAspectRatio();
- F32 meters_per_pixel = height_meters / height_pixels;
- up = getUpAxis() * meters_per_pixel * gViewerWindowp->getDisplayScale().mV[VY];
- right = -1.f * pixel_aspect * meters_per_pixel * getLeftAxis() *
- gViewerWindowp->getDisplayScale().mV[VX];
- }
- LLVector3 LLViewerCamera::roundToPixel(const LLVector3& pos_agent)
- {
- F32 dist = (pos_agent - getOrigin()).length();
- // Convert to screen space and back, preserving the depth.
- LLCoordGL screen_point;
- if (!projectPosAgentToScreen(pos_agent, screen_point, false))
- {
- // Off the screen, just return the original position.
- return pos_agent;
- }
- LLVector3 ray_dir;
- projectScreenToPosAgent(screen_point.mX, screen_point.mY, &ray_dir);
- ray_dir -= getOrigin();
- ray_dir.normalize();
- LLVector3 pos_agent_rounded = getOrigin() + ray_dir*dist;
- #if 0
- LLVector3 pixel_x, pixel_y;
- getPixelVectors(pos_agent_rounded, pixel_y, pixel_x);
- pos_agent_rounded += 0.5f*pixel_x, 0.5f*pixel_y;
- #endif
- return pos_agent_rounded;
- }
- bool LLViewerCamera::cameraUnderWater() const
- {
- // *TODO: figure out how to handle this case.
- if (gPipeline.mHeroProbeManager.isMirrorPass())
- {
- return false;
- }
- LLViewerRegion* regionp = gWorld.getRegionFromPosAgent(getOrigin());
- if (!regionp)
- {
- regionp = gAgent.getRegion();
- }
- return regionp && getOrigin().mV[VZ] < regionp->getWaterHeight();
- }
- bool LLViewerCamera::areVertsVisible(LLViewerObject* volumep, bool all_verts)
- {
- LLDrawable* drawablep = volumep->mDrawable;
- if (!drawablep)
- {
- return false;
- }
- LLVolume* volume = volumep->getVolume();
- if (!volume)
- {
- return false;
- }
- LLVOVolume* vo_volume = (LLVOVolume*)volumep;
- vo_volume->updateRelativeXform();
- LLMatrix4 render_mat(vo_volume->getRenderRotation(),
- LLVector4(vo_volume->getRenderPosition()));
- LLMatrix4a render_mata;
- render_mata.loadu(render_mat);
- LLMatrix4a mata;
- mata.loadu(vo_volume->getRelativeXform());
- S32 num_faces = volume->getNumVolumeFaces();
- for (S32 i = 0; i < num_faces; ++i)
- {
- const LLVolumeFace& face = volume->getVolumeFace(i);
- for (U32 v = 0, count = face.mNumVertices; v < count; ++v)
- {
- const LLVector4a& src_vec = face.mPositions[v];
- LLVector4a vec;
- mata.affineTransform(src_vec, vec);
- if (drawablep->isActive())
- {
- LLVector4a t = vec;
- render_mata.affineTransform(t, vec);
- }
- bool in_frustum = pointInFrustum(LLVector3(vec.getF32ptr())) > 0;
- if ((!in_frustum && all_verts) || (in_frustum && !all_verts))
- {
- return !all_verts;
- }
- }
- }
- return all_verts;
- }
- // Changes local camera and broadcasts change
- //virtual
- void LLViewerCamera::setView(F32 vertical_fov_rads)
- {
- if (gCubeSnapshot) // Should not happen
- {
- llassert(false);
- return;
- }
- F32 old_fov = getView();
- // Cap the FoV
- vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView());
- if (vertical_fov_rads == old_fov) return;
- // Send the new value to the simulator
- LLMessageSystem* msg = gMessageSystemp;
- msg->newMessageFast(_PREHASH_AgentFOV);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
- msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
- msg->addU32Fast(_PREHASH_CircuitCode, msg->mOurCircuitCode);
- msg->nextBlockFast(_PREHASH_FOVBlock);
- msg->addU32Fast(_PREHASH_GenCounter, 0);
- msg->addF32Fast(_PREHASH_VerticalAngle, vertical_fov_rads);
- gAgent.sendReliableMessage();
- // Sync the camera with the new value
- LLCamera::setView(vertical_fov_rads); // Call base implementation
- }
- void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads)
- {
- vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView());
- //MK
- if (gRLenabled)
- {
- if (gRLInterface.mCamZoomMax < EXTREMUM &&
- DEFAULT_FIELD_OF_VIEW / vertical_fov_rads > gRLInterface.mCamZoomMax)
- {
- vertical_fov_rads = DEFAULT_FIELD_OF_VIEW / gRLInterface.mCamZoomMax;
- }
- if (gRLInterface.mCamZoomMin > -EXTREMUM &&
- DEFAULT_FIELD_OF_VIEW / vertical_fov_rads < gRLInterface.mCamZoomMin)
- {
- vertical_fov_rads = DEFAULT_FIELD_OF_VIEW / gRLInterface.mCamZoomMin;
- }
- }
- //mk
- setView(vertical_fov_rads);
- mCameraFOVDefault = vertical_fov_rads;
- mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
- }
- bool LLViewerCamera::isDefaultFOVChanged()
- {
- static LLCachedControl<bool> ignore_fov_zoom(gSavedSettings,
- "IgnoreFOVZoomForLODs");
- if (mCameraFOVDefault != mPrevCameraFOVDefault)
- {
- mPrevCameraFOVDefault = mCameraFOVDefault;
- return !ignore_fov_zoom;
- }
- return false;
- }
|