aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llface.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llface.cpp445
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
224void LLFace::setWorldMatrix(const LLMatrix4 &mat) 226void 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
229void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) 231void 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
454void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) 457void 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
1248const F32 LEAST_IMPORTANCE = 0.05f ;
1249const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ;
1250
1251F32 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
1306F32 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
1335F32 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
1363const S8 FACE_IMPORTANCE_LEVEL = 4 ;
1364const 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} } ;
1366const 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
1370F32 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
1401BOOL LLFace::verify(const U32* indices_array) const 1356BOOL 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//
1548void LLFace::removeAtlas()
1549{
1550 setAtlasInUse(FALSE) ;
1551 mAtlasInfop = NULL ;
1552}
1553
1554const LLTextureAtlas* LLFace::getAtlas()const
1555{
1556 if(mAtlasInfop)
1557 {
1558 return mAtlasInfop->getAtlas() ;
1559 }
1560 return NULL ;
1561}
1562
1563const LLVector2* LLFace::getTexCoordOffset()const
1564{
1565 if(isAtlasInUse())
1566 {
1567 return mAtlasInfop->getTexCoordOffset() ;
1568 }
1569 return NULL ;
1570}
1571const LLVector2* LLFace::getTexCoordScale() const
1572{
1573 if(isAtlasInUse())
1574 {
1575 return mAtlasInfop->getTexCoordScale() ;
1576 }
1577 return NULL ;
1578}
1579
1580BOOL LLFace::isAtlasInUse()const
1581{
1582 return mUsingAtlas ;
1583}
1584
1585BOOL 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
1608void 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
1637LLTextureAtlasSlot* LLFace::getAtlasInfo()
1638{
1639 return mAtlasInfop ;
1640}
1641
1642void 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
1654LLImageGL* 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.
1666BOOL 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}