aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llface.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llface.cpp193
1 files changed, 189 insertions, 4 deletions
diff --git a/linden/indra/newview/llface.cpp b/linden/indra/newview/llface.cpp
index 69edcca..dab1dac 100644
--- a/linden/indra/newview/llface.cpp
+++ b/linden/indra/newview/llface.cpp
@@ -52,6 +52,7 @@
52#include "llvovolume.h" 52#include "llvovolume.h"
53#include "pipeline.h" 53#include "pipeline.h"
54#include "llviewerregion.h" 54#include "llviewerregion.h"
55#include "llviewerwindow.h"
55 56
56#define LL_MAX_INDICES_COUNT 1000000 57#define LL_MAX_INDICES_COUNT 1000000
57 58
@@ -174,11 +175,19 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
174 mLastGeomIndex = mGeomIndex; 175 mLastGeomIndex = mGeomIndex;
175 mLastIndicesCount = mIndicesCount; 176 mLastIndicesCount = mIndicesCount;
176 mLastIndicesIndex = mIndicesIndex; 177 mLastIndicesIndex = mIndicesIndex;
178
179 mImportanceToCamera = 0.f ;
180 mBoundingSphereRadius = 0.0f ;
177} 181}
178 182
179 183
180void LLFace::destroy() 184void LLFace::destroy()
181{ 185{
186 if(mTexture.notNull())
187 {
188 mTexture->removeFace(this) ;
189 }
190
182 if (mDrawPoolp) 191 if (mDrawPoolp)
183 { 192 {
184 mDrawPoolp->removeFace(this); 193 mDrawPoolp->removeFace(this);
@@ -199,7 +208,7 @@ void LLFace::destroy()
199 } 208 }
200 } 209 }
201 } 210 }
202 211
203 setDrawInfo(NULL); 212 setDrawInfo(NULL);
204 213
205 mDrawablep = NULL; 214 mDrawablep = NULL;
@@ -247,9 +256,29 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep)
247 } 256 }
248 mDrawPoolp = new_pool; 257 mDrawPoolp = new_pool;
249 } 258 }
250 mTexture = texturep; 259
260 setTexture(texturep) ;
251} 261}
252 262
263void LLFace::setTexture(LLViewerImage* tex)
264{
265 if(mTexture == tex)
266 {
267 return ;
268 }
269
270 if(mTexture.notNull())
271 {
272 mTexture->removeFace(this) ;
273 }
274
275 mTexture = tex ;
276
277 if(mTexture.notNull())
278 {
279 mTexture->addFace(this) ;
280 }
281}
253 282
254void LLFace::setTEOffset(const S32 te_offset) 283void LLFace::setTEOffset(const S32 te_offset)
255{ 284{
@@ -698,7 +727,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
698 } 727 }
699 728
700 mCenterLocal = (newMin+newMax)*0.5f; 729 mCenterLocal = (newMin+newMax)*0.5f;
701 730 LLVector3 tmp = (newMin - newMax) ;
731 mBoundingSphereRadius = tmp.length() * 0.5f ;
732
702 updateCenterAgent(); 733 updateCenterAgent();
703 } 734 }
704 735
@@ -865,6 +896,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
865 { 896 {
866 mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); 897 mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);
867 } 898 }
899
868 if (rebuild_tcoord) 900 if (rebuild_tcoord)
869 { 901 {
870 mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); 902 mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
@@ -959,7 +991,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
959 0.75f 991 0.75f
960 }; 992 };
961 993
962 if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny())) 994 if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny())))
963 { 995 {
964 color.mV[3] = U8 (alpha[tep->getShiny()] * 255); 996 color.mV[3] = U8 (alpha[tep->getShiny()] * 255);
965 } 997 }
@@ -1147,6 +1179,159 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
1147 return TRUE; 1179 return TRUE;
1148} 1180}
1149 1181
1182const F32 LEAST_IMPORTANCE = 0.05f ;
1183const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ;
1184
1185F32 LLFace::getTextureVirtualSize()
1186{
1187 F32 radius;
1188 F32 cos_angle_to_view_dir;
1189 mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius);
1190
1191 if (mPixelArea <= 0)
1192 {
1193 return 0.f;
1194 }
1195
1196 //get area of circle in texture space
1197 LLVector2 tdim = mTexExtents[1] - mTexExtents[0];
1198 F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f;
1199 if (texel_area <= 0)
1200 {
1201 // Probably animated, use default
1202 texel_area = 1.f;
1203 }
1204
1205 F32 face_area;
1206 if (mVObjp->isSculpted() && texel_area > 1.f)
1207 {
1208 //sculpts can break assumptions about texel area
1209 face_area = mPixelArea;
1210 }
1211 else
1212 {
1213 //apply texel area to face area to get accurate ratio
1214 //face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
1215 face_area = mPixelArea / llclamp(texel_area, 0.015625f, 1024.f);
1216 }
1217
1218 if(face_area > LLViewerImage::sMaxSmallImageSize)
1219 {
1220 if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res.
1221 {
1222 face_area = LLViewerImage::sMaxSmallImageSize ;
1223 }
1224 else if(face_area > LLViewerImage::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping.
1225 {
1226 if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res.
1227 {
1228 face_area = LLViewerImage::sMinLargeImageSize ;
1229 }
1230 else if(mTexture.notNull() && mTexture->isLargeImage())
1231 {
1232 face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius );
1233 }
1234 }
1235 }
1236
1237 return face_area;
1238}
1239
1240F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
1241{
1242 //get area of circle around face
1243 LLVector3 center = getPositionAgent();
1244 LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f;
1245
1246 LLVector3 lookAt = center - LLViewerCamera::getInstance()->getOrigin();
1247 F32 dist = lookAt.normVec() ;
1248
1249 //get area of circle around node
1250 F32 app_angle = atanf(size.length()/dist);
1251 radius = app_angle*LLDrawable::sCurPixelAngle;
1252 F32 face_area = radius*radius * 3.14159f;
1253
1254 if(dist < mBoundingSphereRadius) //camera is very close
1255 {
1256 cos_angle_to_view_dir = 1.0f ;
1257 mImportanceToCamera = 1.0f ;
1258 }
1259 else
1260 {
1261 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ;
1262 mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ;
1263 }
1264
1265 return face_area ;
1266}
1267
1268//the projection of the face partially overlaps with the screen
1269F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius )
1270{
1271 F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ;
1272 F32 center_angle = acosf(cos_angle_to_view_dir) ;
1273 F32 d = center_angle * LLDrawable::sCurPixelAngle ;
1274
1275 if(d + radius > screen_radius + 5.f)
1276 {
1277 //----------------------------------------------
1278 //calculate the intersection area of two circles
1279 //F32 radius_square = radius * radius ;
1280 //F32 d_square = d * d ;
1281 //F32 screen_radius_square = screen_radius * screen_radius ;
1282 //face_area =
1283 // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) +
1284 // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) -
1285 // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ;
1286 //----------------------------------------------
1287
1288 //the above calculation is too expensive
1289 //the below is a good estimation: bounding box of the bounding sphere:
1290 F32 alpha = 0.5f * (radius + screen_radius - d) / radius ;
1291 alpha = llclamp(alpha, 0.f, 1.f) ;
1292 return alpha * alpha ;
1293 }
1294 return 1.0f ;
1295}
1296
1297const S8 FACE_IMPORTANCE_LEVEL = 4 ;
1298const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight}
1299 {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ;
1300const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight}
1301 {{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}} ;
1302
1303//static
1304F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)
1305{
1306 F32 importance = 0.f ;
1307
1308 if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() &&
1309 dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0])
1310 {
1311 F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
1312 F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
1313
1314 if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f)
1315 {
1316 //if camera moves or rotates too fast, ignore the importance factor
1317 return 0.f ;
1318 }
1319
1320 //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ;
1321
1322 S32 i = 0 ;
1323 for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i);
1324 i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
1325 F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ;
1326
1327 for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ;
1328 i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
1329 importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ;
1330 }
1331
1332 return importance ;
1333}
1334
1150BOOL LLFace::verify(const U32* indices_array) const 1335BOOL LLFace::verify(const U32* indices_array) const
1151{ 1336{
1152 BOOL ok = TRUE; 1337 BOOL ok = TRUE;