diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llface.cpp | 445 |
1 files changed, 275 insertions, 170 deletions
diff --git a/linden/indra/newview/llface.cpp b/linden/indra/newview/llface.cpp index aa8cd15..ae57a3c 100644 --- a/linden/indra/newview/llface.cpp +++ b/linden/indra/newview/llface.cpp | |||
@@ -176,8 +176,8 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) | |||
176 | mLastIndicesCount = mIndicesCount; | 176 | mLastIndicesCount = mIndicesCount; |
177 | mLastIndicesIndex = mIndicesIndex; | 177 | mLastIndicesIndex = mIndicesIndex; |
178 | 178 | ||
179 | mImportanceToCamera = 0.f ; | 179 | mAtlasInfop = NULL ; |
180 | mBoundingSphereRadius = 0.0f ; | 180 | mUsingAtlas = FALSE ; |
181 | } | 181 | } |
182 | 182 | ||
183 | 183 | ||
@@ -205,12 +205,14 @@ void LLFace::destroy() | |||
205 | if (group) | 205 | if (group) |
206 | { | 206 | { |
207 | group->dirtyGeom(); | 207 | group->dirtyGeom(); |
208 | gPipeline.markRebuild(group, TRUE); | ||
208 | } | 209 | } |
209 | } | 210 | } |
210 | } | 211 | } |
211 | 212 | ||
212 | setDrawInfo(NULL); | 213 | setDrawInfo(NULL); |
213 | 214 | ||
215 | removeAtlas(); | ||
214 | mDrawablep = NULL; | 216 | mDrawablep = NULL; |
215 | mVObjp = NULL; | 217 | mVObjp = NULL; |
216 | } | 218 | } |
@@ -223,7 +225,7 @@ void LLFace::initClass() | |||
223 | 225 | ||
224 | void LLFace::setWorldMatrix(const LLMatrix4 &mat) | 226 | void LLFace::setWorldMatrix(const LLMatrix4 &mat) |
225 | { | 227 | { |
226 | llerrs << "Faces on this drawable are not independently modifiable\n" << llendl; | 228 | llwarns << "Faces on this drawable are not independently modifiable\n" << llendl; |
227 | } | 229 | } |
228 | 230 | ||
229 | void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) | 231 | void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) |
@@ -232,7 +234,7 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) | |||
232 | 234 | ||
233 | if (!new_pool) | 235 | if (!new_pool) |
234 | { | 236 | { |
235 | llerrs << "Setting pool to null!" << llendl; | 237 | llwarns << "Setting pool to null!" << llendl; |
236 | } | 238 | } |
237 | 239 | ||
238 | if (new_pool != mDrawPoolp) | 240 | if (new_pool != mDrawPoolp) |
@@ -270,6 +272,7 @@ void LLFace::setTexture(LLViewerImage* tex) | |||
270 | if(mTexture.notNull()) | 272 | if(mTexture.notNull()) |
271 | { | 273 | { |
272 | mTexture->removeFace(this) ; | 274 | mTexture->removeFace(this) ; |
275 | removeAtlas() ; | ||
273 | } | 276 | } |
274 | 277 | ||
275 | mTexture = tex ; | 278 | mTexture = tex ; |
@@ -453,8 +456,15 @@ void LLFace::renderForSelect(U32 data_mask) | |||
453 | 456 | ||
454 | void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) | 457 | void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) |
455 | { | 458 | { |
456 | if(mDrawablep.isNull() || mVertexBuffer.isNull() || mDrawablep->getSpatialGroup() == NULL || | 459 | if (mDrawablep->getSpatialGroup() == NULL) |
457 | mDrawablep->getSpatialGroup()->isState(LLSpatialGroup::GEOM_DIRTY)) | 460 | { |
461 | return; | ||
462 | } | ||
463 | |||
464 | mDrawablep->getSpatialGroup()->rebuildGeom(); | ||
465 | mDrawablep->getSpatialGroup()->rebuildMesh(); | ||
466 | |||
467 | if(mDrawablep.isNull() || mVertexBuffer.isNull()) | ||
458 | { | 468 | { |
459 | return; | 469 | return; |
460 | } | 470 | } |
@@ -473,17 +483,10 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) | |||
473 | glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix); | 483 | glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix); |
474 | } | 484 | } |
475 | 485 | ||
476 | setFaceColor(color); | 486 | glColor4fv(color.mV); |
477 | renderSetColor(); | ||
478 | |||
479 | mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); | 487 | mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); |
480 | #if !LL_RELEASE_FOR_DOWNLOAD | ||
481 | LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); | ||
482 | #endif | ||
483 | mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); | 488 | mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); |
484 | 489 | ||
485 | unsetFaceColor(); | ||
486 | unsetFaceColor(); | ||
487 | gGL.popMatrix(); | 490 | gGL.popMatrix(); |
488 | } | 491 | } |
489 | } | 492 | } |
@@ -727,8 +730,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, | |||
727 | } | 730 | } |
728 | 731 | ||
729 | mCenterLocal = (newMin+newMax)*0.5f; | 732 | mCenterLocal = (newMin+newMax)*0.5f; |
730 | LLVector3 tmp = (newMin - newMax) ; | 733 | // LLVector3 tmp = (newMin - newMax) ; |
731 | mBoundingSphereRadius = tmp.length() * 0.5f ; | 734 | // mBoundingSphereRadius = tmp.length() * 0.5f ; |
732 | 735 | ||
733 | updateCenterAgent(); | 736 | updateCenterAgent(); |
734 | } | 737 | } |
@@ -963,6 +966,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, | |||
963 | mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); | 966 | mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); |
964 | } | 967 | } |
965 | 968 | ||
969 | F32 tcoord_xoffset = 0.f ; | ||
970 | F32 tcoord_yoffset = 0.f ; | ||
971 | F32 tcoord_xscale = 1.f ; | ||
972 | F32 tcoord_yscale = 1.f ; | ||
973 | BOOL in_atlas = FALSE ; | ||
974 | |||
966 | if (rebuild_tcoord) | 975 | if (rebuild_tcoord) |
967 | { | 976 | { |
968 | mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); | 977 | mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); |
@@ -970,6 +979,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, | |||
970 | { | 979 | { |
971 | mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); | 980 | mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); |
972 | } | 981 | } |
982 | |||
983 | in_atlas = isAtlasInUse() ; | ||
984 | if(in_atlas) | ||
985 | { | ||
986 | const LLVector2* tmp = getTexCoordOffset() ; | ||
987 | tcoord_xoffset = tmp->mV[0] ; | ||
988 | tcoord_yoffset = tmp->mV[1] ; | ||
989 | |||
990 | tmp = getTexCoordScale() ; | ||
991 | tcoord_xscale = tmp->mV[0] ; | ||
992 | tcoord_yscale = tmp->mV[1] ; | ||
993 | } | ||
973 | } | 994 | } |
974 | if (rebuild_color) | 995 | if (rebuild_color) |
975 | { | 996 | { |
@@ -1057,7 +1078,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, | |||
1057 | 0.75f | 1078 | 0.75f |
1058 | }; | 1079 | }; |
1059 | 1080 | ||
1060 | if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny()))) | 1081 | if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny())) |
1061 | { | 1082 | { |
1062 | color.mV[3] = U8 (alpha[tep->getShiny()] * 255); | 1083 | color.mV[3] = U8 (alpha[tep->getShiny()] * 255); |
1063 | } | 1084 | } |
@@ -1179,6 +1200,93 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, | |||
1179 | xform(tc, cos_ang, sin_ang, os, ot, ms, mt); | 1200 | xform(tc, cos_ang, sin_ang, os, ot, ms, mt); |
1180 | } | 1201 | } |
1181 | 1202 | ||
1203 | if(in_atlas) | ||
1204 | { | ||
1205 | // | ||
1206 | //manually calculate tex-coord per vertex for varying address modes. | ||
1207 | //should be removed if shader can handle this. | ||
1208 | // | ||
1209 | |||
1210 | S32 int_part = 0 ; | ||
1211 | switch(mTexture->getAddressMode()) | ||
1212 | { | ||
1213 | case LLTexUnit::TAM_CLAMP: | ||
1214 | if(tc.mV[0] < 0.f) | ||
1215 | { | ||
1216 | tc.mV[0] = 0.f ; | ||
1217 | } | ||
1218 | else if(tc.mV[0] > 1.f) | ||
1219 | { | ||
1220 | tc.mV[0] = 1.f; | ||
1221 | } | ||
1222 | |||
1223 | if(tc.mV[1] < 0.f) | ||
1224 | { | ||
1225 | tc.mV[1] = 0.f ; | ||
1226 | } | ||
1227 | else if(tc.mV[1] > 1.f) | ||
1228 | { | ||
1229 | tc.mV[1] = 1.f; | ||
1230 | } | ||
1231 | break; | ||
1232 | case LLTexUnit::TAM_MIRROR: | ||
1233 | if(tc.mV[0] < 0.f) | ||
1234 | { | ||
1235 | tc.mV[0] = -tc.mV[0] ; | ||
1236 | } | ||
1237 | int_part = (S32)tc.mV[0] ; | ||
1238 | if(int_part & 1) //odd number | ||
1239 | { | ||
1240 | tc.mV[0] = int_part + 1 - tc.mV[0] ; | ||
1241 | } | ||
1242 | else //even number | ||
1243 | { | ||
1244 | tc.mV[0] -= int_part ; | ||
1245 | } | ||
1246 | |||
1247 | if(tc.mV[1] < 0.f) | ||
1248 | { | ||
1249 | tc.mV[1] = -tc.mV[1] ; | ||
1250 | } | ||
1251 | int_part = (S32)tc.mV[1] ; | ||
1252 | if(int_part & 1) //odd number | ||
1253 | { | ||
1254 | tc.mV[1] = int_part + 1 - tc.mV[1] ; | ||
1255 | } | ||
1256 | else //even number | ||
1257 | { | ||
1258 | tc.mV[1] -= int_part ; | ||
1259 | } | ||
1260 | break; | ||
1261 | case LLTexUnit::TAM_WRAP: | ||
1262 | if(tc.mV[0] > 1.f) | ||
1263 | tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; | ||
1264 | else if(tc.mV[0] < -1.f) | ||
1265 | tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; | ||
1266 | |||
1267 | if(tc.mV[1] > 1.f) | ||
1268 | tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; | ||
1269 | else if(tc.mV[1] < -1.f) | ||
1270 | tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; | ||
1271 | |||
1272 | if(tc.mV[0] < 0.f) | ||
1273 | { | ||
1274 | tc.mV[0] = 1.0f + tc.mV[0] ; | ||
1275 | } | ||
1276 | if(tc.mV[1] < 0.f) | ||
1277 | { | ||
1278 | tc.mV[1] = 1.0f + tc.mV[1] ; | ||
1279 | } | ||
1280 | break; | ||
1281 | default: | ||
1282 | break; | ||
1283 | } | ||
1284 | |||
1285 | tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; | ||
1286 | tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; | ||
1287 | } | ||
1288 | |||
1289 | |||
1182 | *tex_coords++ = tc; | 1290 | *tex_coords++ = tc; |
1183 | 1291 | ||
1184 | if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) | 1292 | if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) |
@@ -1245,159 +1353,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, | |||
1245 | return TRUE; | 1353 | return TRUE; |
1246 | } | 1354 | } |
1247 | 1355 | ||
1248 | const F32 LEAST_IMPORTANCE = 0.05f ; | ||
1249 | const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ; | ||
1250 | |||
1251 | F32 LLFace::getTextureVirtualSize() | ||
1252 | { | ||
1253 | F32 radius; | ||
1254 | F32 cos_angle_to_view_dir; | ||
1255 | mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius); | ||
1256 | |||
1257 | if (mPixelArea <= 0) | ||
1258 | { | ||
1259 | return 0.f; | ||
1260 | } | ||
1261 | |||
1262 | //get area of circle in texture space | ||
1263 | LLVector2 tdim = mTexExtents[1] - mTexExtents[0]; | ||
1264 | F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; | ||
1265 | if (texel_area <= 0) | ||
1266 | { | ||
1267 | // Probably animated, use default | ||
1268 | texel_area = 1.f; | ||
1269 | } | ||
1270 | |||
1271 | F32 face_area; | ||
1272 | if (mVObjp->isSculpted() && texel_area > 1.f) | ||
1273 | { | ||
1274 | //sculpts can break assumptions about texel area | ||
1275 | face_area = mPixelArea; | ||
1276 | } | ||
1277 | else | ||
1278 | { | ||
1279 | //apply texel area to face area to get accurate ratio | ||
1280 | //face_area /= llclamp(texel_area, 1.f/64.f, 16.f); | ||
1281 | face_area = mPixelArea / llclamp(texel_area, 0.015625f, 1024.f); | ||
1282 | } | ||
1283 | |||
1284 | if(face_area > LLViewerImage::sMaxSmallImageSize) | ||
1285 | { | ||
1286 | if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res. | ||
1287 | { | ||
1288 | face_area = LLViewerImage::sMaxSmallImageSize ; | ||
1289 | } | ||
1290 | else if(face_area > LLViewerImage::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. | ||
1291 | { | ||
1292 | if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res. | ||
1293 | { | ||
1294 | face_area = LLViewerImage::sMinLargeImageSize ; | ||
1295 | } | ||
1296 | else if(mTexture.notNull() && mTexture->isLargeImage()) | ||
1297 | { | ||
1298 | face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius ); | ||
1299 | } | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | return face_area; | ||
1304 | } | ||
1305 | |||
1306 | F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) | ||
1307 | { | ||
1308 | //get area of circle around face | ||
1309 | LLVector3 center = getPositionAgent(); | ||
1310 | LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f; | ||
1311 | |||
1312 | LLVector3 lookAt = center - LLViewerCamera::getInstance()->getOrigin(); | ||
1313 | F32 dist = lookAt.normVec() ; | ||
1314 | |||
1315 | //get area of circle around node | ||
1316 | F32 app_angle = atanf(size.length()/dist); | ||
1317 | radius = app_angle*LLDrawable::sCurPixelAngle; | ||
1318 | F32 face_area = radius*radius * 3.14159f; | ||
1319 | |||
1320 | if(dist < mBoundingSphereRadius) //camera is very close | ||
1321 | { | ||
1322 | cos_angle_to_view_dir = 1.0f ; | ||
1323 | mImportanceToCamera = 1.0f ; | ||
1324 | } | ||
1325 | else | ||
1326 | { | ||
1327 | cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; | ||
1328 | mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; | ||
1329 | } | ||
1330 | |||
1331 | return face_area ; | ||
1332 | } | ||
1333 | |||
1334 | //the projection of the face partially overlaps with the screen | ||
1335 | F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ) | ||
1336 | { | ||
1337 | F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ; | ||
1338 | F32 center_angle = acosf(cos_angle_to_view_dir) ; | ||
1339 | F32 d = center_angle * LLDrawable::sCurPixelAngle ; | ||
1340 | |||
1341 | if(d + radius > screen_radius + 5.f) | ||
1342 | { | ||
1343 | //---------------------------------------------- | ||
1344 | //calculate the intersection area of two circles | ||
1345 | //F32 radius_square = radius * radius ; | ||
1346 | //F32 d_square = d * d ; | ||
1347 | //F32 screen_radius_square = screen_radius * screen_radius ; | ||
1348 | //face_area = | ||
1349 | // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) + | ||
1350 | // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) - | ||
1351 | // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ; | ||
1352 | //---------------------------------------------- | ||
1353 | |||
1354 | //the above calculation is too expensive | ||
1355 | //the below is a good estimation: bounding box of the bounding sphere: | ||
1356 | F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; | ||
1357 | alpha = llclamp(alpha, 0.f, 1.f) ; | ||
1358 | return alpha * alpha ; | ||
1359 | } | ||
1360 | return 1.0f ; | ||
1361 | } | ||
1362 | |||
1363 | const S8 FACE_IMPORTANCE_LEVEL = 4 ; | ||
1364 | const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight} | ||
1365 | {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ; | ||
1366 | const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight} | ||
1367 | {{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}} ; | ||
1368 | |||
1369 | //static | ||
1370 | F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) | ||
1371 | { | ||
1372 | F32 importance = 0.f ; | ||
1373 | |||
1374 | if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && | ||
1375 | dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) | ||
1376 | { | ||
1377 | F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; | ||
1378 | F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); | ||
1379 | |||
1380 | if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f) | ||
1381 | { | ||
1382 | //if camera moves or rotates too fast, ignore the importance factor | ||
1383 | return 0.f ; | ||
1384 | } | ||
1385 | |||
1386 | //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ; | ||
1387 | |||
1388 | S32 i = 0 ; | ||
1389 | for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i); | ||
1390 | i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; | ||
1391 | F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ; | ||
1392 | |||
1393 | for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ; | ||
1394 | i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; | ||
1395 | importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ; | ||
1396 | } | ||
1397 | |||
1398 | return importance ; | ||
1399 | } | ||
1400 | |||
1401 | BOOL LLFace::verify(const U32* indices_array) const | 1356 | BOOL LLFace::verify(const U32* indices_array) const |
1402 | { | 1357 | { |
1403 | BOOL ok = TRUE; | 1358 | BOOL ok = TRUE; |
@@ -1586,3 +1541,153 @@ LLVector3 LLFace::getPositionAgent() const | |||
1586 | return mCenterLocal * getRenderMatrix(); | 1541 | return mCenterLocal * getRenderMatrix(); |
1587 | } | 1542 | } |
1588 | } | 1543 | } |
1544 | |||
1545 | // | ||
1546 | //atlas | ||
1547 | // | ||
1548 | void LLFace::removeAtlas() | ||
1549 | { | ||
1550 | setAtlasInUse(FALSE) ; | ||
1551 | mAtlasInfop = NULL ; | ||
1552 | } | ||
1553 | |||
1554 | const LLTextureAtlas* LLFace::getAtlas()const | ||
1555 | { | ||
1556 | if(mAtlasInfop) | ||
1557 | { | ||
1558 | return mAtlasInfop->getAtlas() ; | ||
1559 | } | ||
1560 | return NULL ; | ||
1561 | } | ||
1562 | |||
1563 | const LLVector2* LLFace::getTexCoordOffset()const | ||
1564 | { | ||
1565 | if(isAtlasInUse()) | ||
1566 | { | ||
1567 | return mAtlasInfop->getTexCoordOffset() ; | ||
1568 | } | ||
1569 | return NULL ; | ||
1570 | } | ||
1571 | const LLVector2* LLFace::getTexCoordScale() const | ||
1572 | { | ||
1573 | if(isAtlasInUse()) | ||
1574 | { | ||
1575 | return mAtlasInfop->getTexCoordScale() ; | ||
1576 | } | ||
1577 | return NULL ; | ||
1578 | } | ||
1579 | |||
1580 | BOOL LLFace::isAtlasInUse()const | ||
1581 | { | ||
1582 | return mUsingAtlas ; | ||
1583 | } | ||
1584 | |||
1585 | BOOL LLFace::canUseAtlas()const | ||
1586 | { | ||
1587 | //no drawable or no spatial group, do not use atlas | ||
1588 | if(!mDrawablep || !mDrawablep->getSpatialGroup()) | ||
1589 | { | ||
1590 | return FALSE ; | ||
1591 | } | ||
1592 | |||
1593 | //if bump face, do not use atlas | ||
1594 | if(getTextureEntry() && getTextureEntry()->getBumpmap()) | ||
1595 | { | ||
1596 | return FALSE ; | ||
1597 | } | ||
1598 | |||
1599 | //if animated texture, do not use atlas | ||
1600 | if(isState(TEXTURE_ANIM)) | ||
1601 | { | ||
1602 | return FALSE ; | ||
1603 | } | ||
1604 | |||
1605 | return TRUE ; | ||
1606 | } | ||
1607 | |||
1608 | void LLFace::setAtlasInUse(BOOL flag) | ||
1609 | { | ||
1610 | //no valid atlas to use. | ||
1611 | if(flag && (!mAtlasInfop || !mAtlasInfop->isValid())) | ||
1612 | { | ||
1613 | flag = FALSE ; | ||
1614 | } | ||
1615 | |||
1616 | if(!flag && !mUsingAtlas) | ||
1617 | { | ||
1618 | return ; | ||
1619 | } | ||
1620 | |||
1621 | // | ||
1622 | //at this stage (flag || mUsingAtlas) is always true. | ||
1623 | // | ||
1624 | |||
1625 | //rebuild the tex coords | ||
1626 | if(mDrawablep) | ||
1627 | { | ||
1628 | gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_TCOORD); | ||
1629 | mUsingAtlas = flag ; | ||
1630 | } | ||
1631 | else | ||
1632 | { | ||
1633 | mUsingAtlas = FALSE ; | ||
1634 | } | ||
1635 | } | ||
1636 | |||
1637 | LLTextureAtlasSlot* LLFace::getAtlasInfo() | ||
1638 | { | ||
1639 | return mAtlasInfop ; | ||
1640 | } | ||
1641 | |||
1642 | void LLFace::setAtlasInfo(LLTextureAtlasSlot* atlasp) | ||
1643 | { | ||
1644 | if(mAtlasInfop != atlasp) | ||
1645 | { | ||
1646 | if(mAtlasInfop) | ||
1647 | { | ||
1648 | //llwarns << "Atlas slot changed!" << llendl ; | ||
1649 | } | ||
1650 | mAtlasInfop = atlasp ; | ||
1651 | } | ||
1652 | } | ||
1653 | |||
1654 | LLImageGL* LLFace::getGLTexture() const | ||
1655 | { | ||
1656 | if(isAtlasInUse()) | ||
1657 | { | ||
1658 | return (LLImageGL*)mAtlasInfop->getAtlas() ; | ||
1659 | } | ||
1660 | |||
1661 | return (LLImageGL*)mTexture ; | ||
1662 | } | ||
1663 | |||
1664 | //switch to atlas or switch back to gl texture | ||
1665 | //return TRUE if using atlas. | ||
1666 | BOOL LLFace::switchTexture() | ||
1667 | { | ||
1668 | //no valid atlas or texture | ||
1669 | if(!mAtlasInfop || !mAtlasInfop->isValid() || !mTexture) | ||
1670 | { | ||
1671 | return FALSE ; | ||
1672 | } | ||
1673 | |||
1674 | if(mTexture->getTexelsInAtlas() >= (U32)mVSize || mTexture->getTexelsInAtlas() >= mTexture->getTexelsInGLTexture()) | ||
1675 | { | ||
1676 | //switch to use atlas | ||
1677 | //atlas resolution is qualified, use it. | ||
1678 | if(!mUsingAtlas) | ||
1679 | { | ||
1680 | setAtlasInUse(TRUE) ; | ||
1681 | } | ||
1682 | } | ||
1683 | else //if atlas not qualified. | ||
1684 | { | ||
1685 | //switch back to GL texture | ||
1686 | if(mUsingAtlas && mTexture->isGLTextureCreated() && mTexture->getDiscardLevel() < mTexture->getDiscardLevelInAtlas()) | ||
1687 | { | ||
1688 | setAtlasInUse(FALSE) ; | ||
1689 | } | ||
1690 | } | ||
1691 | |||
1692 | return mUsingAtlas ; | ||
1693 | } | ||