diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llface.cpp | 193 |
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 | ||
180 | void LLFace::destroy() | 184 | void 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 | ||
263 | void 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 | ||
254 | void LLFace::setTEOffset(const S32 te_offset) | 283 | void 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 | ||
1182 | const F32 LEAST_IMPORTANCE = 0.05f ; | ||
1183 | const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ; | ||
1184 | |||
1185 | F32 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 | |||
1240 | F32 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 | ||
1269 | F32 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 | |||
1297 | const S8 FACE_IMPORTANCE_LEVEL = 4 ; | ||
1298 | const 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} } ; | ||
1300 | const 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 | ||
1304 | F32 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 | |||
1150 | BOOL LLFace::verify(const U32* indices_array) const | 1335 | BOOL LLFace::verify(const U32* indices_array) const |
1151 | { | 1336 | { |
1152 | BOOL ok = TRUE; | 1337 | BOOL ok = TRUE; |