summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/lltexlayer.cpp4
-rw-r--r--indra/newview/llvoavatar.cpp244
2 files changed, 204 insertions, 44 deletions
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 1feb987682..d8b9bc2329 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -581,6 +581,10 @@ void LLTexLayerSetBuffer::doUpdate()
}
restartUpdateTimer();
+
+ // need to swtich to using this layerset if this is the first update
+ // after getting the lowest LOD
+ mTexLayerSet->getAvatar()->updateMeshTextures();
// Print out notification that we uploaded this texture.
if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 6392aad248..c688338000 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -702,8 +702,10 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i);
}
- mDirtyMesh = 2; // Dirty geometry, need to regenerate.
+ mDirtyMesh = TRUE; // Dirty geometry, need to regenerate.
mMeshTexturesDirty = FALSE;
+ mShadow0Facep = NULL;
+ mShadow1Facep = NULL;
mHeadp = NULL;
mIsBuilt = FALSE;
@@ -739,6 +741,12 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mRippleTimeLast = 0.f;
+ mShadowImagep = LLViewerTextureManager::getFetchedTextureFromFile("foot_shadow.j2c");
+
+ // GL NOT ACTIVE HERE
+ //gGL.getTexUnit(0)->bind(mShadowImagep.get());
+ //mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
+
mInAir = FALSE;
mStepOnLand = TRUE;
@@ -1967,7 +1975,7 @@ void LLVOAvatar::updateMeshData()
}
if(num_vertices < 1)//skip empty meshes
{
- continue ;
+ break ;
}
if(last_v_num > 0)//put the last inserted part into next vertex buffer.
{
@@ -1989,8 +1997,6 @@ void LLVOAvatar::updateMeshData()
// resize immediately
facep->setSize(num_vertices, num_indices);
- bool terse_update = false;
-
if(facep->mVertexBuffer.isNull())
{
facep->mVertexBuffer = new LLVertexBufferAvatar();
@@ -1998,16 +2004,8 @@ void LLVOAvatar::updateMeshData()
}
else
{
- if (facep->mVertexBuffer->getRequestedIndices() == num_indices &&
- facep->mVertexBuffer->getRequestedVerts() == num_vertices)
- {
- terse_update = true;
- }
- else
- {
facep->mVertexBuffer->resizeBuffer(num_vertices, num_indices) ;
}
- }
facep->setGeomIndex(0);
facep->setIndicesIndex(0);
@@ -2021,7 +2019,7 @@ void LLVOAvatar::updateMeshData()
for(S32 k = j ; k < part_index ; k++)
{
- mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update);
+ mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR);
}
stop_glerror();
@@ -2431,6 +2429,12 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
LLJoint::sNumUpdates = 0;
LLJoint::sNumTouches = 0;
+ // *NOTE: this is necessary for the floating name text above your head.
+ if (mDrawable.notNull())
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_SHADOW, TRUE);
+ }
+
BOOL visible = isVisible() || mNeedsAnimUpdate;
// update attachments positions
@@ -3783,20 +3787,13 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
return num_indices;
}
- LLFace* face = mDrawable->getFace(0);
-
- bool needs_rebuild = !face || face->mVertexBuffer.isNull() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY);
-
- if (needs_rebuild || mDirtyMesh)
+ if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
{ //LOD changed or new mesh created, allocate new vertex buffer if needed
- if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4)
- {
updateMeshData();
- mDirtyMesh = 0;
+ mDirtyMesh = FALSE;
mNeedsSkin = TRUE;
mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
}
- }
if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0)
{
@@ -4043,6 +4040,54 @@ U32 LLVOAvatar::renderRigid()
return num_indices;
}
+U32 LLVOAvatar::renderFootShadows()
+{
+ U32 num_indices = 0;
+
+ if (!mIsBuilt)
+ {
+ return 0;
+ }
+
+ if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead()))
+ {
+ return 0;
+ }
+
+ if (!mIsBuilt)
+ {
+ return 0;
+ }
+
+ // Don't render foot shadows if your lower body is completely invisible.
+ // (non-humanoid avatars rule!)
+ if (!isTextureVisible(TEX_LOWER_BAKED))
+ {
+ return 0;
+ }
+
+ // Update the shadow, tractor, and text label geometry.
+ if (mDrawable->isState(LLDrawable::REBUILD_SHADOW) && !isImpostor())
+ {
+ updateShadowFaces();
+ mDrawable->clearState(LLDrawable::REBUILD_SHADOW);
+ }
+
+ U32 foot_mask = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD0;
+
+ LLGLDepthTest test(GL_TRUE, GL_FALSE);
+ //render foot shadows
+ LLGLEnable blend(GL_BLEND);
+ gGL.getTexUnit(0)->bind(mShadowImagep, TRUE);
+ glColor4fv(mShadow0Facep->getRenderColor().mV);
+ mShadow0Facep->renderIndexed(foot_mask);
+ glColor4fv(mShadow1Facep->getRenderColor().mV);
+ mShadow1Facep->renderIndexed(foot_mask);
+
+ return num_indices;
+}
+
U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel)
{
if (!mImpostor.isComplete())
@@ -4168,6 +4213,11 @@ void LLVOAvatar::updateTextures()
{
setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea)));
}
+
+ if( render_avatar )
+ {
+ mShadowImagep->addTextureStats(mPixelArea);
+ }
}
@@ -5434,7 +5484,7 @@ BOOL LLVOAvatar::updateJointLODs()
if (res)
{
sNumLODChangesThisFrame++;
- dirtyMesh(2);
+ dirtyMesh();
return TRUE;
}
}
@@ -5458,9 +5508,18 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
mDrawable->addFace(poolp, NULL);
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR);
+ LLFace *facep;
+
+ // Add faces for the foot shadows
+ facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep);
+ mShadow0Facep = facep;
+
+ facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep);
+ mShadow1Facep = facep;
+
mNumInitFaces = mDrawable->getNumFaces() ;
- dirtyMesh(2);
+ dirtyMesh();
return mDrawable;
}
@@ -5500,6 +5559,107 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
}
//-----------------------------------------------------------------------------
+// updateShadowFaces()
+//-----------------------------------------------------------------------------
+void LLVOAvatar::updateShadowFaces()
+{
+ LLFace *face0p = mShadow0Facep;
+ LLFace *face1p = mShadow1Facep;
+
+ //
+ // render avatar shadows
+ //
+ if (mInAir || mUpdatePeriod >= IMPOSTOR_PERIOD)
+ {
+ face0p->setSize(0, 0);
+ face1p->setSize(0, 0);
+ return;
+ }
+
+ LLSprite sprite(mShadowImagep.notNull() ? mShadowImagep->getID() : LLUUID::null);
+ sprite.setFollow(FALSE);
+ const F32 cos_angle = gSky.getSunDirection().mV[2];
+ F32 cos_elev = sqrt(1 - cos_angle * cos_angle);
+ if (cos_angle < 0) cos_elev = -cos_elev;
+ sprite.setSize(0.4f + cos_elev * 0.8f, 0.3f);
+ LLVector3 sun_vec = gSky.mVOSkyp ? gSky.mVOSkyp->getToSun() : LLVector3(0.f, 0.f, 0.f);
+
+ if (mShadowImagep->hasGLTexture())
+ {
+ LLVector3 normal;
+ LLVector3d shadow_pos;
+ LLVector3 shadow_pos_agent;
+ F32 foot_height;
+
+ if (mFootLeftp)
+ {
+ LLVector3 joint_world_pos = mFootLeftp->getWorldPosition();
+ // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now
+ // but we make an explicit ray trace call in expectation of future improvements
+ resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos),
+ gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
+ shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos);
+ foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ];
+
+ // Pull sprite in direction of surface normal
+ shadow_pos_agent += normal * SHADOW_OFFSET_AMT;
+
+ // Render sprite
+ sprite.setNormal(normal);
+ if (isSelf() && gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+ {
+ sprite.setColor(0.f, 0.f, 0.f, 0.f);
+ }
+ else
+ {
+ sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f));
+ }
+ sprite.setPosition(shadow_pos_agent);
+
+ LLVector3 foot_to_knee = mKneeLeftp->getWorldPosition() - joint_world_pos;
+ //foot_to_knee.normalize();
+ foot_to_knee -= projected_vec(foot_to_knee, sun_vec);
+ sprite.setYaw(azimuth(sun_vec - foot_to_knee));
+
+ sprite.updateFace(*face0p);
+ }
+
+ if (mFootRightp)
+ {
+ LLVector3 joint_world_pos = mFootRightp->getWorldPosition();
+ // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now
+ // but we make an explicit ray trace call in expectation of future improvements
+ resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos),
+ gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
+ shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos);
+ foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ];
+
+ // Pull sprite in direction of surface normal
+ shadow_pos_agent += normal * SHADOW_OFFSET_AMT;
+
+ // Render sprite
+ sprite.setNormal(normal);
+ if (isSelf() && gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+ {
+ sprite.setColor(0.f, 0.f, 0.f, 0.f);
+ }
+ else
+ {
+ sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f));
+ }
+ sprite.setPosition(shadow_pos_agent);
+
+ LLVector3 foot_to_knee = mKneeRightp->getWorldPosition() - joint_world_pos;
+ //foot_to_knee.normalize();
+ foot_to_knee -= projected_vec(foot_to_knee, sun_vec);
+ sprite.setYaw(azimuth(sun_vec - foot_to_knee));
+
+ sprite.updateFace(*face1p);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
// updateSexDependentLayerSets()
//-----------------------------------------------------------------------------
void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
@@ -5514,12 +5674,9 @@ void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
//-----------------------------------------------------------------------------
void LLVOAvatar::dirtyMesh()
{
- dirtyMesh(1);
-}
-void LLVOAvatar::dirtyMesh(S32 priority)
-{
- mDirtyMesh = llmax(mDirtyMesh, priority);
+ mDirtyMesh = TRUE;
}
+
//-----------------------------------------------------------------------------
// hideSkirt()
//-----------------------------------------------------------------------------
@@ -5553,6 +5710,7 @@ BOOL LLVOAvatar::setParent(LLViewerObject* parent)
void LLVOAvatar::addChild(LLViewerObject *childp)
{
+ childp->extractAttachmentItemID(); // find the inventory item this object is associated with.
LLViewerObject::addChild(childp);
if (childp->mDrawable)
{
@@ -5642,15 +5800,6 @@ BOOL LLVOAvatar::canAttachMoreObjects() const
}
//-----------------------------------------------------------------------------
-// canAttachMoreObjects()
-// Returns true if we can attach <n> more objects.
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::canAttachMoreObjects(U32 n) const
-{
- return (getNumAttachments() + n) <= MAX_AGENT_ATTACHMENTS;
-}
-
-//-----------------------------------------------------------------------------
// lazyAttach()
//-----------------------------------------------------------------------------
void LLVOAvatar::lazyAttach()
@@ -6102,10 +6251,14 @@ void LLVOAvatar::updateMeshTextures()
// When an avatar is changing clothes and not in Appearance mode,
// use the last-known good baked texture until it finish the first
// render of the new layerset.
+
+ const BOOL layerset_invalid = !mBakedTextureDatas[i].mTexLayerSet
+ || !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized()
+ || !mBakedTextureDatas[i].mTexLayerSet->isLocalTextureDataAvailable();
+
use_lkg_baked_layer[i] = (!is_layer_baked[i]
&& (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR)
- && mBakedTextureDatas[i].mTexLayerSet
- && !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized());
+ && layerset_invalid);
if (use_lkg_baked_layer[i])
{
mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE);
@@ -7793,15 +7946,18 @@ BOOL LLVOAvatar::updateLOD()
BOOL res = updateJointLODs();
LLFace* facep = mDrawable->getFace(0);
- if (facep->mVertexBuffer.isNull())
+ if (facep->mVertexBuffer.isNull() ||
+ (LLVertexBuffer::sEnableVBOs &&
+ ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) !=
+ (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE))))
{
- dirtyMesh(2);
+ mDirtyMesh = TRUE;
}
- if (mDirtyMesh >= 2 || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
+ if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
{ //LOD changed or new mesh created, allocate new vertex buffer if needed
updateMeshData();
- mDirtyMesh = 0;
+ mDirtyMesh = FALSE;
mNeedsSkin = TRUE;
mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
}