summaryrefslogtreecommitdiff
path: root/indra/newview/llviewercamera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewercamera.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llviewercamera.cpp214
1 files changed, 136 insertions, 78 deletions
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index f65baea6ca..57a0195d23 100644..100755
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -2,40 +2,37 @@
* @file llviewercamera.cpp
* @brief LLViewerCamera class implementation
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* 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
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * 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
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
+#define LLVIEWERCAMERA_CPP
#include "llviewercamera.h"
// Viewer includes
#include "llagent.h"
+#include "llagentcamera.h"
+#include "llmatrix4a.h"
#include "llviewercontrol.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
@@ -52,11 +49,15 @@
#include "llglheaders.h"
#include "llquaternion.h"
#include "llwindow.h" // getPixelAspectRatio()
+#include "lltracerecording.h"
// System includes
#include <iomanip> // for setprecision
-U32 LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+LLTrace::CountStatHandle<> LLViewerCamera::sVelocityStat("camera_velocity");
+LLTrace::CountStatHandle<> LLViewerCamera::sAngularVelocityStat("camera_angular_velocity");
+
+LLViewerCamera::eCameraID LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
//glu pick matrix implementation borrowed from Mesa3D
glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport)
@@ -105,14 +106,20 @@ glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up)
}
+// Build time optimization, generate this once in .cpp file
+template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInstance();
+
LLViewerCamera::LLViewerCamera() : LLCamera()
{
calcProjection(getFar());
mCameraFOVDefault = 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;
gSavedSettings.getControl("CameraAngle")->getCommitSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle, this, _2));
}
@@ -133,9 +140,6 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
mLastPointOfInterest = point_of_interest;
- // constrain to max distance from avatar
- LLVector3 camera_offset = center - gAgent.getPositionAgent();
-
LLViewerRegion * regp = gAgent.getRegion();
F32 water_height = (NULL != regp) ? regp->getWaterHeight() : 0.f;
@@ -151,15 +155,22 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
setOriginAndLookAt(origin, up_direction, point_of_interest);
- F32 dpos = (center - last_position).magVec();
+ mVelocityDir = origin - last_position ;
+ F32 dpos = mVelocityDir.normVec() ;
LLQuaternion rotation;
rotation.shortestArc(last_axis, getAtAxis());
F32 x, y, z;
F32 drot;
rotation.getAngleAxis(&drot, &x, &y, &z);
- mVelocityStat.addValue(dpos);
- mAngularVelocityStat.addValue(drot);
+
+ add(sVelocityStat, dpos);
+ add(sAngularVelocityStat, drot);
+
+ mAverageSpeed = LLTrace::get_frame_recording().getPeriodMeanPerSec(sVelocityStat, 50);
+ mAverageAngularSpeed = LLTrace::get_frame_recording().getPeriodMeanPerSec(sAngularVelocityStat);
+ 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
@@ -208,8 +219,15 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const
void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip, BOOL no_hacks)
{
GLint* viewport = (GLint*) gGLViewport;
- GLdouble* model = gGLModelView;
- GLdouble* proj = gGLProjection;
+ F64 model[16];
+ F64 proj[16];
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ model[i] = (F64) gGLModelView[i];
+ proj[i] = (F64) gGLProjection[i];
+ }
+
GLdouble objX,objY,objZ;
LLVector3 frust[8];
@@ -301,7 +319,7 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
{
F32 fov_y, aspect;
fov_y = RAD_TO_DEG * getView();
- BOOL z_default_near, z_default_far = FALSE;
+ BOOL z_default_far = FALSE;
if (z_far <= 0)
{
z_default_far = TRUE;
@@ -309,14 +327,13 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
}
if (z_near <= 0)
{
- z_default_near = TRUE;
z_near = getNear();
}
aspect = getAspect();
// Load camera view matrix
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.loadIdentity();
glh::matrix4f proj_mat;
@@ -324,7 +341,12 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
{
// make a tiny little viewport
// anything drawn into this viewport will be "selected"
- GLint* viewport = (GLint*) gGLViewport;
+
+ 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);
@@ -335,7 +357,7 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
}
else
{
- z_far = gAgent.mDrawDistance;
+ z_far = gAgentCamera.mDrawDistance;
}
}
else
@@ -370,14 +392,14 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
proj_mat *= gl_perspective(fov_y,aspect,z_near,z_far);
- glLoadMatrixf(proj_mat.m);
+ gGL.loadMatrix(proj_mat.m);
for (U32 i = 0; i < 16; i++)
{
gGLProjection[i] = proj_mat.m[i];
}
- glMatrixMode( GL_MODELVIEW );
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
glh::matrix4f modelview((GLfloat*) OGL_TO_CFR_ROTATION);
@@ -387,14 +409,17 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
modelview *= glh::matrix4f(ogl_matrix);
- glLoadMatrixf(modelview.m);
+ gGL.loadMatrix(modelview.m);
if (for_selection && (width > 1 || height > 1))
{
- calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f,
- (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f,
- (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f,
- (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f);
+ // 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);
}
@@ -402,7 +427,6 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
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];
@@ -410,14 +434,6 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
}
updateFrustumPlanes(*this);
-
- /*if (gSavedSettings.getBOOL("CameraOffset"))
- {
- glMatrixMode(GL_PROJECTION);
- glTranslatef(0,0,-50);
- glRotatef(20.0,1,0,0);
- glMatrixMode(GL_MODELVIEW);
- }*/
}
@@ -425,11 +441,20 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
// screen coordinates to the agent's region.
void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 screen_y, LLVector3* pos_agent) const
{
-
GLdouble x, y, z;
+
+ F64 mdlv[16];
+ F64 proj[16];
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ mdlv[i] = (F64) gGLModelView[i];
+ proj[i] = (F64) gGLProjection[i];
+ }
+
gluUnProject(
GLdouble(screen_x), GLdouble(screen_y), 0.0,
- gGLModelView, gGLProjection, (GLint*)gGLViewport,
+ mdlv, proj, (GLint*)gGLViewport,
&x,
&y,
&z );
@@ -459,15 +484,24 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
}
}
- LLRect world_view_rect = gViewerWindow->getWorldViewRect();
+ LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
S32 viewport[4];
viewport[0] = world_view_rect.mLeft;
viewport[1] = world_view_rect.mBottom;
viewport[2] = world_view_rect.getWidth();
viewport[3] = world_view_rect.getHeight();
+ F64 mdlv[16];
+ F64 proj[16];
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ mdlv[i] = (F64) gGLModelView[i];
+ proj[i] = (F64) gGLProjection[i];
+ }
+
if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ],
- gGLModelView, gGLProjection, (GLint*)viewport,
+ mdlv, proj, (GLint*)viewport,
&x, &y, &z))
{
// convert screen coordinates to virtual UI coordinates
@@ -475,7 +509,7 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
y /= gViewerWindow->getDisplayScale().mV[VY];
// should now have the x,y coords of grab_point in screen space
- LLRect world_view_rect = gViewerWindow->getVirtualWorldViewRect();
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
// convert to pixel coordinates
S32 int_x = lltrunc(x);
@@ -485,14 +519,14 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
if (clamp)
{
- if (int_x < world_view_rect.mLeft)
+ if (int_x < world_rect.mLeft)
{
- out_point.mX = world_view_rect.mLeft;
+ out_point.mX = world_rect.mLeft;
valid = FALSE;
}
- else if (int_x > world_view_rect.mRight)
+ else if (int_x > world_rect.mRight)
{
- out_point.mX = world_view_rect.mRight;
+ out_point.mX = world_rect.mRight;
valid = FALSE;
}
else
@@ -500,14 +534,14 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
out_point.mX = int_x;
}
- if (int_y < world_view_rect.mBottom)
+ if (int_y < world_rect.mBottom)
{
- out_point.mY = world_view_rect.mBottom;
+ out_point.mY = world_rect.mBottom;
valid = FALSE;
}
- else if (int_y > world_view_rect.mTop)
+ else if (int_y > world_rect.mTop)
{
- out_point.mY = world_view_rect.mTop;
+ out_point.mY = world_rect.mTop;
valid = FALSE;
}
else
@@ -521,19 +555,19 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
out_point.mX = int_x;
out_point.mY = int_y;
- if (int_x < world_view_rect.mLeft)
+ if (int_x < world_rect.mLeft)
{
valid = FALSE;
}
- else if (int_x > world_view_rect.mRight)
+ else if (int_x > world_rect.mRight)
{
valid = FALSE;
}
- if (int_y < world_view_rect.mBottom)
+ if (int_y < world_rect.mBottom)
{
valid = FALSE;
}
- else if (int_y > world_view_rect.mTop)
+ else if (int_y > world_rect.mTop)
{
valid = FALSE;
}
@@ -562,22 +596,32 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
in_front = FALSE;
}
- LLRect world_view_rect = gViewerWindow->getWorldViewRect();
+ LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
S32 viewport[4];
viewport[0] = world_view_rect.mLeft;
viewport[1] = world_view_rect.mBottom;
viewport[2] = world_view_rect.getWidth();
viewport[3] = world_view_rect.getHeight();
GLdouble x, y, z; // object's window coords, GL-style
+
+ F64 mdlv[16];
+ F64 proj[16];
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ mdlv[i] = (F64) gGLModelView[i];
+ proj[i] = (F64) gGLProjection[i];
+ }
+
if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY],
- pos_agent.mV[VZ], gGLModelView,
- gGLProjection, (GLint*)viewport,
+ pos_agent.mV[VZ], mdlv,
+ proj, (GLint*)viewport,
&x, &y, &z))
{
x /= gViewerWindow->getDisplayScale().mV[VX];
y /= gViewerWindow->getDisplayScale().mV[VY];
// should now have the x,y coords of grab_point in screen space
- const LLRect& world_rect = gViewerWindow->getVirtualWorldViewRect();
+ const LLRect& world_rect = gViewerWindow->getWorldViewRectScaled();
// ...sanity check
S32 int_x = lltrunc(x);
@@ -738,6 +782,10 @@ LLVector3 LLViewerCamera::roundToPixel(const LLVector3 &pos_agent)
BOOL LLViewerCamera::cameraUnderWater() const
{
+ if(!gAgent.getRegion())
+ {
+ return FALSE ;
+ }
return getOrigin().mV[VZ] < gAgent.getRegion()->getWaterHeight();
}
@@ -764,21 +812,29 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition()));
+ LLMatrix4a render_mata;
+ render_mata.loadu(render_mat);
+ LLMatrix4a mata;
+ mata.loadu(mat);
+
num_faces = volume->getNumVolumeFaces();
for (i = 0; i < num_faces; i++)
{
const LLVolumeFace& face = volume->getVolumeFace(i);
- for (U32 v = 0; v < face.mVertices.size(); v++)
+ for (U32 v = 0; v < face.mNumVertices; v++)
{
- LLVector4 vec = LLVector4(face.mVertices[v].mPosition) * mat;
+ const LLVector4a& src_vec = face.mPositions[v];
+ LLVector4a vec;
+ mata.affineTransform(src_vec, vec);
if (drawablep->isActive())
{
- vec = vec * render_mat;
+ LLVector4a t = vec;
+ render_mata.affineTransform(t, vec);
}
- BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0;
+ BOOL in_frustum = pointInFrustum(LLVector3(vec.getF32ptr())) > 0;
if (( !in_frustum && all_verts) ||
(in_frustum && !all_verts))
@@ -818,10 +874,12 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
LLCamera::setView(vertical_fov_rads); // call base implementation
}
-void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) {
+void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads)
+{
vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView());
setView(vertical_fov_rads);
mCameraFOVDefault = vertical_fov_rads;
+ mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
}