summaryrefslogtreecommitdiff
path: root/indra/llmath/llcamera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmath/llcamera.cpp')
-rw-r--r--indra/llmath/llcamera.cpp218
1 files changed, 151 insertions, 67 deletions
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index 3b9ba9d0f7..bad4d00fd6 100644
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -2,30 +2,25 @@
* @file llcamera.cpp
* @brief Implementation of the LLCamera class.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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$
*/
@@ -44,39 +39,46 @@ LLCamera::LLCamera() :
mNearPlane(DEFAULT_NEAR_PLANE),
mFarPlane(DEFAULT_FAR_PLANE),
mFixedDistance(-1.f),
- mPlaneCount(6)
+ mPlaneCount(6),
+ mFrustumCornerDist(0.f)
{
calculateFrustumPlanes();
}
-LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) :
+LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) :
LLCoordFrame(),
- mView(z_field_of_view),
- mAspect(aspect_ratio),
mViewHeightInPixels(view_height_in_pixels),
- mNearPlane(near_plane),
- mFarPlane(far_plane),
mFixedDistance(-1.f),
- mPlaneCount(6)
+ mPlaneCount(6),
+ mFrustumCornerDist(0.f)
{
- if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; }
- else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; }
+ mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
+ mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
+ if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE;
+ mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE);
- if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; }
- else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; }
-
- if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; }
- else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; }
+ setView(vertical_fov_rads);
+}
- if (mFarPlane < 0) { mFarPlane = DEFAULT_FAR_PLANE; }
- else if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; }
- else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; }
- calculateFrustumPlanes();
-}
+// ---------------- LLCamera::getFoo() member functions ----------------
+F32 LLCamera::getMinView() const
+{
+ // minimum vertical fov needs to be constrained in narrow windows.
+ return mAspect > 1
+ ? MIN_FIELD_OF_VIEW // wide views
+ : MIN_FIELD_OF_VIEW * 1/mAspect; // clamps minimum width in narrow views
+}
+F32 LLCamera::getMaxView() const
+{
+ // maximum vertical fov needs to be constrained in wide windows.
+ return mAspect > 1
+ ? MAX_FIELD_OF_VIEW / mAspect // clamps maximum width in wide views
+ : MAX_FIELD_OF_VIEW; // narrow views
+}
// ---------------- LLCamera::setFoo() member functions ----------------
@@ -92,11 +94,9 @@ void LLCamera::disableUserClipPlane()
mPlaneCount = 6;
}
-void LLCamera::setView(F32 field_of_view)
+void LLCamera::setView(F32 vertical_fov_rads)
{
- mView = field_of_view;
- if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; }
- else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; }
+ mView = llclamp(vertical_fov_rads, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW);
calculateFrustumPlanes();
}
@@ -110,27 +110,21 @@ void LLCamera::setViewHeightInPixels(S32 height)
void LLCamera::setAspect(F32 aspect_ratio)
{
- mAspect = aspect_ratio;
- if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; }
- else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; }
+ mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
calculateFrustumPlanes();
}
void LLCamera::setNear(F32 near_plane)
{
- mNearPlane = near_plane;
- if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; }
- else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; }
+ mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
calculateFrustumPlanes();
}
void LLCamera::setFar(F32 far_plane)
{
- mFarPlane = far_plane;
- if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; }
- else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; }
+ mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE);
calculateFrustumPlanes();
}
@@ -180,28 +174,99 @@ S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
U8 mask = 0;
S32 result = 2;
- for (U32 i = 0; i < mPlaneCount; i++)
- {
- mask = mAgentPlanes[i].mask;
- LLPlane p = mAgentPlanes[i].p;
- LLVector3 n = LLVector3(p);
- float d = p.mV[3];
- LLVector3 rscale = radius.scaledVec(scaler[mask]);
-
- LLVector3 minp = center - rscale;
- LLVector3 maxp = center + rscale;
+ /*if (mFrustumCornerDist > 0.f && radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist)
+ { //box is larger than frustum, check frustum quads against box planes
- if (n * minp > -d)
+ static const LLVector3 dir[] =
{
- return 0;
+ LLVector3(1, 0, 0),
+ LLVector3(-1, 0, 0),
+ LLVector3(0, 1, 0),
+ LLVector3(0, -1, 0),
+ LLVector3(0, 0, 1),
+ LLVector3(0, 0, -1)
+ };
+
+ U32 quads[] =
+ {
+ 0, 1, 2, 3,
+ 0, 1, 5, 4,
+ 2, 3, 7, 6,
+ 3, 0, 7, 4,
+ 1, 2, 6, 4,
+ 4, 5, 6, 7
+ };
+
+ result = 0;
+
+ BOOL total_inside = TRUE;
+ for (U32 i = 0; i < 6; i++)
+ {
+ LLVector3 p = center + radius.scaledVec(dir[i]);
+ F32 d = -p*dir[i];
+
+ for (U32 j = 0; j < 6; j++)
+ { //for each quad
+ F32 dist = mAgentFrustum[quads[j*4+0]]*dir[i] + d;
+ if (dist > 0)
+ { //at least one frustum point is outside the AABB
+ total_inside = FALSE;
+ for (U32 k = 1; k < 4; k++)
+ { //for each other point on quad
+ if ( mAgentFrustum[quads[j*4+k]]*dir[i]+d <= 0.f)
+ { //quad is straddling some plane of AABB
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ for (U32 k = 1; k < 4; k++)
+ {
+ if (mAgentFrustum[quads[j*4+k]]*dir[i]+d > 0.f)
+ {
+ return 1;
+ }
+ }
+ }
+ }
}
-
- if (n * maxp > -d)
+
+ if (total_inside)
{
result = 1;
}
}
+ else*/
+ {
+ for (U32 i = 0; i < mPlaneCount; i++)
+ {
+ mask = mAgentPlanes[i].mask;
+ if (mask == 0xff)
+ {
+ continue;
+ }
+ LLPlane p = mAgentPlanes[i].p;
+ LLVector3 n = LLVector3(p);
+ float d = p.mV[3];
+ LLVector3 rscale = radius.scaledVec(scaler[mask]);
+
+ LLVector3 minp = center - rscale;
+ LLVector3 maxp = center + rscale;
+
+ if (n * minp > -d)
+ {
+ return 0;
+ }
+
+ if (n * maxp > -d)
+ {
+ result = 1;
+ }
+ }
+ }
+
return result;
}
@@ -229,6 +294,10 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& r
}
mask = mAgentPlanes[i].mask;
+ if (mask == 0xff)
+ {
+ continue;
+ }
LLPlane p = mAgentPlanes[i].p;
LLVector3 n = LLVector3(p);
float d = p.mV[3];
@@ -372,6 +441,11 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius)
int res = 2;
for (int i = 0; i < 6; i++)
{
+ if (mAgentPlanes[i].mask == 0xff)
+ {
+ continue;
+ }
+
float d = mAgentPlanes[i].p.dist(sphere_center);
if (d > radius)
@@ -557,9 +631,19 @@ U8 LLCamera::calcPlaneMask(const LLPlane& plane)
return mask;
}
-void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
+void LLCamera::ignoreAgentFrustumPlane(S32 idx)
{
+ if (idx < 0 || idx > (S32) mPlaneCount)
+ {
+ return;
+ }
+
+ mAgentPlanes[idx].mask = 0xff;
+ mAgentPlanes[idx].p.clearVec();
+}
+void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
+{
for (int i = 0; i < 8; i++)
{
mAgentFrustum[i] = frust[i];