Meshy update. Mostly related to cost calculations... mostly.

This commit is contained in:
Shyotl
2011-08-28 04:05:36 -05:00
parent c66065b688
commit 59d50f3062
11 changed files with 622 additions and 199 deletions

View File

@@ -93,6 +93,8 @@ F32 LLVOVolume::sLODFactor = 1.f;
F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
F32 LLVOVolume::sDistanceFactor = 1.0f;
S32 LLVOVolume::sNumLODChanges = 0;
S32 LLVOVolume::mRenderComplexity_last = 0;
S32 LLVOVolume::mRenderComplexity_current = 0;
LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
: LLViewerObject(id, pcode, regionp),
@@ -489,18 +491,24 @@ BOOL LLVOVolume::isVisible() const
return FALSE ;
}
void LLVOVolume::updateTextureVirtualSize()
void LLVOVolume::updateTextureVirtualSize(bool forced)
{
// Update the pixel area of all faces
if(!isVisible() || mDrawable.isNull())
{
if(mDrawable.isNull())
return;
}
if(!forced)
{
if(!isVisible())
{
return;
}
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
{
return;
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
{
return;
}
}
static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable");
@@ -559,12 +567,12 @@ void LLVOVolume::updateTextureVirtualSize()
// Animating textures also rez badly in Snowglobe because the
// actual displayed area is only a fraction (corresponding to one
// frame) of the animating texture. Let's fix that here:
if (mTextureAnimp && mTextureAnimp->mScaleS > 0.0f && mTextureAnimp->mScaleT > 0.0f)
/* if (mTextureAnimp && mTextureAnimp->mScaleS > 0.0f && mTextureAnimp->mScaleT > 0.0f)
{
// Adjust to take into account the actual frame size which is only a
// portion of the animating texture
vsize = vsize / mTextureAnimp->mScaleS / mTextureAnimp->mScaleT;
}
}*/
if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) ||
(vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE))
@@ -578,13 +586,17 @@ void LLVOVolume::updateTextureVirtualSize()
if (vsize < min_vsize) min_vsize = vsize;
if (vsize > max_vsize) max_vsize = vsize;
}
// else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
// {
// F32 pri = imagep->getDecodePriority();
// pri = llmax(pri, 0.0f);
// if (pri < min_vsize) min_vsize = pri;
// if (pri > max_vsize) max_vsize = pri;
// }
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ;
if(img)
{
F32 pri = img->getDecodePriority();
pri = llmax(pri, 0.0f);
if (pri < min_vsize) min_vsize = pri;
if (pri > max_vsize) max_vsize = pri;
}
}
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
{
F32 pri = mPixelArea;
@@ -657,10 +669,10 @@ void LLVOVolume::updateTextureVirtualSize()
{
setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
}
// else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
// {
// setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
// }
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
}
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
{
setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
@@ -995,19 +1007,11 @@ BOOL LLVOVolume::calcLOD()
F32 distance;
#if MESH_ENABLED
if (mDrawable->isState(LLDrawable::RIGGED))
if (mDrawable->isState(LLDrawable::RIGGED) && getAvatar())
{
LLVOAvatar* avatar = getAvatar();
if(avatar)
{
distance = avatar->mDrawable->mDistanceWRTCamera;
radius = avatar->getBinRadius();
}
else
{
distance = mDrawable->mDistanceWRTCamera;
radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length();
}
distance = avatar->mDrawable->mDistanceWRTCamera;
radius = avatar->getBinRadius();
}
else
#endif //MESH_ENABLED
@@ -2211,8 +2215,270 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const
return mDrawable->getWorldMatrix();
}
// Returns a base cost and adds textures to passed in set.
// total cost is returned value + 5 * size of the resulting set.
// Cannot include cost of textures, as they may be re-used in linked
// children, and cost should only be increased for unique textures -Nyx
U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
{
// Get access to params we'll need at various points.
// Skip if this is object doesn't have a volume (e.g. is an avatar).
BOOL has_volume = (getVolume() != NULL);
LLVolumeParams volume_params;
LLPathParams path_params;
LLProfileParams profile_params;
U32 num_triangles = 0;
// per-prim costs
static const U32 ARC_PARTICLE_COST = 1; // determined experimentally
static const U32 ARC_PARTICLE_MAX = 2048; // default values
static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested
static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims
static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face
// per-prim multipliers
static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance
static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance
static const F32 ARC_FLEXI_MULT = 5; // tested based on performance
static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance
static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance
static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance
static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact
static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance
static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance
F32 shame = 0;
U32 invisi = 0;
U32 shiny = 0;
U32 glow = 0;
U32 alpha = 0;
U32 flexi = 0;
U32 animtex = 0;
U32 particles = 0;
U32 bump = 0;
U32 planar = 0;
U32 weighted_mesh = 0;
U32 produces_light = 0;
U32 media_faces = 0;
const LLDrawable* drawablep = mDrawable;
U32 num_faces = drawablep->getNumFaces();
if (has_volume)
{
volume_params = getVolume()->getParams();
path_params = volume_params.getPathParams();
profile_params = volume_params.getProfileParams();
F32 weighted_triangles = -1.0;
getStreamingCost(NULL, NULL, &weighted_triangles);
if (weighted_triangles > 0.0)
{
num_triangles = (U32)(weighted_triangles);
}
}
if (num_triangles == 0)
{
num_triangles = 4;
}
if (isSculpted())
{
if (isMesh())
{
// base cost is dependent on mesh complexity
// note that 3 is the highest LOD as of the time of this coding.
S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(),3);
if ( size > 0)
{
if (gMeshRepo.getSkinInfo(volume_params.getSculptID(), this))
{
// weighted attachment - 1 point for every 3 bytes
weighted_mesh = 1;
}
}
else
{
// something went wrong - user should know their content isn't render-free
return 0;
}
}
else
{
const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT);
LLUUID sculpt_id = sculpt_params->getSculptTexture();
if (textures.find(sculpt_id) == textures.end())
{
LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id);
if (texture)
{
S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (texture->getFullHeight() / 128.f + texture->getFullWidth() / 128.f));
textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost));
}
}
}
}
if (isFlexible())
{
flexi = 1;
}
if (isParticleSource())
{
particles = 1;
}
if (getIsLight())
{
produces_light = 1;
}
for (U32 i = 0; i < num_faces; ++i)
{
const LLFace* face = drawablep->getFace(i);
const LLTextureEntry* te = face->getTextureEntry();
const LLViewerTexture* img = face->getTexture();
if (img)
{
if (textures.find(img->getID()) == textures.end())
{
S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f));
textures.insert(texture_cost_t::value_type(img->getID(), texture_cost));
}
}
if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
{
alpha = 1;
}
else if (img && img->getPrimaryFormat() == GL_ALPHA)
{
invisi = 1;
}
/*if (face->hasMedia())
{
media_faces++;
}*/
if (te)
{
if (te->getBumpmap())
{
// bump is a multiplier, don't add per-face
bump = 1;
}
if (te->getShiny())
{
// shiny is a multiplier, don't add per-face
shiny = 1;
}
if (te->getGlow() > 0.f)
{
// glow is a multiplier, don't add per-face
glow = 1;
}
if (face->mTextureMatrix != NULL)
{
animtex = 1;
}
if (te->getTexGen())
{
planar = 1;
}
}
}
// shame currently has the "base" cost of 1 point per 15 triangles, min 2.
shame = num_triangles * 5.f;
shame = shame < 2.f ? 2.f : shame;
// multiply by per-face modifiers
if (planar)
{
shame *= planar * ARC_PLANAR_COST;
}
if (animtex)
{
shame *= animtex * ARC_ANIM_TEX_COST;
}
if (alpha)
{
shame *= alpha * ARC_ALPHA_COST;
}
if(invisi)
{
shame *= invisi * ARC_INVISI_COST;
}
if (glow)
{
shame *= glow * ARC_GLOW_MULT;
}
if (bump)
{
shame *= bump * ARC_BUMP_MULT;
}
if (shiny)
{
shame *= shiny * ARC_SHINY_MULT;
}
// multiply shame by multipliers
if (weighted_mesh)
{
shame *= weighted_mesh * ARC_WEIGHTED_MESH;
}
if (flexi)
{
shame *= flexi * ARC_FLEXI_MULT;
}
// add additional costs
if (particles)
{
const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData);
const LLPartData *part_data = &(part_sys_data->mPartData);
U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate));
num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles;
F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f;
shame += num_particles * part_size * ARC_PARTICLE_COST;
}
if (produces_light)
{
shame += ARC_LIGHT_COST;
}
if (media_faces)
{
shame += media_faces * ARC_MEDIA_FACE_COST;
}
if (shame > mRenderComplexity_current)
{
mRenderComplexity_current = (S32)shame;
}
return (U32)shame;
}
#if MESH_ENABLED
F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const
{
F32 radius = getScale().length()*0.5f;
@@ -2220,7 +2486,7 @@ F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
{
LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD);
return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD, unscaled_value);
}
else
{
@@ -2234,12 +2500,18 @@ F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
header["medium_lod"]["size"] = counts[2] * 10;
header["high_lod"]["size"] = counts[3] * 10;
return LLMeshRepository::getStreamingCost(header, radius);
return LLMeshRepository::getStreamingCost(header, radius, NULL, NULL, -1, unscaled_value);
}
}
#endif //MESH_ENABLED
//static
void LLVOVolume::updateRenderComplexity()
{
mRenderComplexity_last = mRenderComplexity_current;
mRenderComplexity_current = 0;
}
U32 LLVOVolume::getTriangleCount()
U32 LLVOVolume::getTriangleCount() const
{
U32 count = 0;
LLVolume* volume = getVolume();
@@ -3137,7 +3409,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
}
#endif //MESH_ENABLED
llassert_always(vobj);
vobj->updateTextureVirtualSize();
vobj->updateTextureVirtualSize(true);
vobj->preRebuild();
drawablep->clearState(LLDrawable::HAS_ALPHA);