summaryrefslogtreecommitdiff
path: root/indra/newview/llface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llface.cpp')
-rw-r--r--indra/newview/llface.cpp157
1 files changed, 155 insertions, 2 deletions
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 8ec448e281..c54b83d865 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -52,6 +52,7 @@
#include "llvovolume.h"
#include "pipeline.h"
#include "llviewerregion.h"
+#include "llviewerwindow.h"
#define LL_MAX_INDICES_COUNT 1000000
@@ -175,6 +176,9 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mLastIndicesCount = mIndicesCount;
mLastIndicesIndex = mIndicesIndex;
+ mImportanceToCamera = 0.f ;
+ mBoundingSphereRadius = 0.0f ;
+
mAtlasInfop = NULL ;
mUsingAtlas = FALSE ;
}
@@ -186,6 +190,7 @@ void LLFace::destroy()
{
mTexture->removeFace(this) ;
}
+
if (mDrawPoolp)
{
mDrawPoolp->removeFace(this);
@@ -207,7 +212,7 @@ void LLFace::destroy()
}
}
}
-
+
setDrawInfo(NULL);
removeAtlas();
@@ -256,6 +261,7 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep)
}
mDrawPoolp = new_pool;
}
+
setTexture(texturep) ;
}
@@ -750,7 +756,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
}
mCenterLocal = (newMin+newMax)*0.5f;
-
+ LLVector3 tmp = (newMin - newMax) ;
+ mBoundingSphereRadius = tmp.length() * 0.5f ;
+
updateCenterAgent();
}
@@ -1314,6 +1322,151 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
return TRUE;
}
+const F32 LEAST_IMPORTANCE = 0.05f ;
+const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ;
+
+F32 LLFace::getTextureVirtualSize()
+{
+ F32 radius;
+ F32 cos_angle_to_view_dir;
+ mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius);
+
+ if (mPixelArea <= 0)
+ {
+ return 0.f;
+ }
+
+ //get area of circle in texture space
+ LLVector2 tdim = mTexExtents[1] - mTexExtents[0];
+ F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f;
+ if (texel_area <= 0)
+ {
+ // Probably animated, use default
+ texel_area = 1.f;
+ }
+
+ //apply texel area to face area to get accurate ratio
+ //face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
+ F32 face_area = mPixelArea / llclamp(texel_area, 0.015625f, 128.f);
+
+ if(face_area > LLViewerTexture::sMaxSmallImageSize)
+ {
+ if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res.
+ {
+ static const F32 MAX_LEAST_IMPORTANCE_IMAGE_SIZE = 128.0f * 128.0f ;
+ face_area = llmin(face_area * 0.5f, MAX_LEAST_IMPORTANCE_IMAGE_SIZE) ;
+ }
+ else if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping.
+ {
+ if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res.
+ {
+ face_area = LLViewerTexture::sMinLargeImageSize ;
+ }
+ else if(mTexture.notNull() && mTexture->isLargeImage())
+ {
+ face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius );
+ }
+ }
+ }
+
+ return face_area;
+}
+
+F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
+{
+ //get area of circle around face
+ LLVector3 center = getPositionAgent();
+ LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f;
+
+ LLVector3 lookAt = center - LLViewerCamera::getInstance()->getOrigin();
+ F32 dist = lookAt.normVec() ;
+
+ //get area of circle around node
+ F32 app_angle = atanf(size.length()/dist);
+ radius = app_angle*LLDrawable::sCurPixelAngle;
+ F32 face_area = radius*radius * 3.14159f;
+
+ if(dist < mBoundingSphereRadius) //camera is very close
+ {
+ cos_angle_to_view_dir = 1.0f ;
+ mImportanceToCamera = 1.0f ;
+ }
+ else
+ {
+ cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ;
+ mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ;
+ }
+
+ return face_area ;
+}
+
+//the projection of the face partially overlaps with the screen
+F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius )
+{
+ F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ;
+ F32 center_angle = acosf(cos_angle_to_view_dir) ;
+ F32 d = center_angle * LLDrawable::sCurPixelAngle ;
+
+ if(d + radius > screen_radius + 5.f)
+ {
+ //----------------------------------------------
+ //calculate the intersection area of two circles
+ //F32 radius_square = radius * radius ;
+ //F32 d_square = d * d ;
+ //F32 screen_radius_square = screen_radius * screen_radius ;
+ //face_area =
+ // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) +
+ // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) -
+ // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ;
+ //----------------------------------------------
+
+ //the above calculation is too expensive
+ //the below is a good estimation: bounding box of the bounding sphere:
+ F32 alpha = 0.5f * (radius + screen_radius - d) / radius ;
+ alpha = llclamp(alpha, 0.f, 1.f) ;
+ return alpha * alpha ;
+ }
+ return 1.0f ;
+}
+
+const S8 FACE_IMPORTANCE_LEVEL = 4 ;
+const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight}
+ {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ;
+const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight}
+ {{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ;
+
+//static
+F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)
+{
+ F32 importance = 0.f ;
+
+ if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() &&
+ dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0])
+ {
+ F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
+ F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
+
+ if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f)
+ {
+ //if camera moves or rotates too fast, ignore the importance factor
+ return 0.f ;
+ }
+
+ //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ;
+
+ S32 i = 0 ;
+ for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i);
+ i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
+ F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ;
+
+ for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ;
+ i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
+ importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ;
+ }
+
+ return importance ;
+}
+
BOOL LLFace::verify(const U32* indices_array) const
{
BOOL ok = TRUE;