summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerobject.cpp')
-rw-r--r--indra/newview/llviewerobject.cpp221
1 files changed, 184 insertions, 37 deletions
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 9c91cde09a..395dd0495f 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -284,6 +284,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mOnActiveList(FALSE),
mOnMap(FALSE),
mStatic(FALSE),
+ mSeatCount(0),
mNumFaces(0),
mRotTime(0.f),
mAngularVelocityRot(),
@@ -895,7 +896,12 @@ void LLViewerObject::addChild(LLViewerObject *childp)
if(childp->setParent(this))
{
mChildList.push_back(childp);
- childp->afterReparent();
+ childp->afterReparent();
+
+ if (childp->isAvatar())
+ {
+ mSeatCount++;
+ }
}
}
@@ -924,6 +930,11 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
{
childp->setParent(NULL);
}
+
+ if (childp->isAvatar())
+ {
+ mSeatCount--;
+ }
break;
}
}
@@ -981,21 +992,10 @@ BOOL LLViewerObject::isChild(LLViewerObject *childp) const
return FALSE;
}
-
// returns TRUE if at least one avatar is sitting on this object
BOOL LLViewerObject::isSeat() const
{
- for (child_list_t::const_iterator iter = mChildList.begin();
- iter != mChildList.end(); iter++)
- {
- LLViewerObject* child = *iter;
- if (child->isAvatar())
- {
- return TRUE;
- }
- }
- return FALSE;
-
+ return mSeatCount > 0;
}
BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
@@ -4800,9 +4800,7 @@ LLViewerTexture* LLViewerObject::getBakedTextureForMagicId(const LLUUID& id)
}
LLVOAvatar* avatar = getAvatar();
- if (avatar && !isHUDAttachment()
- && isMesh()
- && getVolume() && getVolume()->getParams().getSculptID().notNull()) // checking for the rigged mesh by params instead of using isRiggedMesh() to avoid false negatives when skin info isn't ready
+ if (avatar && !isHUDAttachment())
{
LLAvatarAppearanceDefines::EBakedTextureIndex texIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::assetIdToBakedTextureIndex(id);
LLViewerTexture* bakedTexture = avatar->getBakedTexture(texIndex);
@@ -4882,22 +4880,78 @@ void LLViewerObject::refreshBakeTexture()
}
}
+void LLViewerObject::updateDiffuseMatParams(const U8 te, LLMaterial* mat, LLViewerTexture *imagep, bool baked_texture)
+{
+ // Objects getting non-alpha texture and alpha mask can result in graphical bugs, like white or red alphas.
+ // To resolve the issue this function provides image format to material and based on format material's
+ // getDiffuseAlphaModeRender() function will decide what value to provide to render
+ //
+ // Unfortunately LLMaterial has no access to diffuse image, so we have to set this data in LLViewerObject
+ // regardles of object being used/seen or frequency of image-updates.
+ mat->setDiffuseBaked(baked_texture);
+
+ if (!baked_texture)
+ {
+ if (imagep->isMissingAsset())
+ {
+ mat->setDiffuseFormatPrimary(0);
+ }
+ else if (0 == imagep->getPrimaryFormat())
+ {
+ // We don't have information about this texture, wait for it
+ mWaitingTextureInfo.insert(uuid_material_mmap_t::value_type(imagep->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
+ // Temporary assume RGBA image
+ mat->setDiffuseFormatPrimary(GL_RGBA);
+ }
+ else
+ {
+ mat->setDiffuseFormatPrimary(imagep->getPrimaryFormat());
+ }
+ }
+}
+
+S32 LLViewerObject::setDiffuseImageAndParams(const U8 te, LLViewerTexture *imagep)
+{
+ LLUUID new_id = imagep->getID();
+ S32 retval = LLPrimitive::setTETexture(te, new_id);
+
+ LLTextureEntry* tep = getTE(te);
+ LLUUID old_image_id = tep->getID();
+
+ LLViewerTexture* baked_texture = getBakedTextureForMagicId(new_id);
+ mTEImages[te] = baked_texture ? baked_texture : imagep;
+ updateAvatarMeshVisibility(new_id, old_image_id);
+
+ LLMaterial* mat = tep->getMaterialParams();
+ if (mat)
+ {
+ // Don't update format from texture (and don't shedule one) if material has no alpha mode set,
+ // just assume RGBA format, format will get updated with setTEMaterialParams call if mode changes
+ if (mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
+ {
+ bool baked = baked_texture != NULL;
+ updateDiffuseMatParams(te, mat, imagep, baked);
+ }
+ else
+ {
+ mat->setDiffuseFormatPrimary(GL_RGBA);
+ }
+ }
+
+ setChanged(TEXTURE);
+ if (mDrawable.notNull())
+ {
+ gPipeline.markTextured(mDrawable);
+ }
+
+ return retval;
+}
+
void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep)
{
if (mTEImages[te] != imagep)
{
- LLUUID old_image_id = getTE(te) ? getTE(te)->getID() : LLUUID::null;
-
- LLPrimitive::setTETexture(te, imagep->getID());
-
- LLViewerTexture* baked_texture = getBakedTextureForMagicId(imagep->getID());
- mTEImages[te] = baked_texture ? baked_texture : imagep;
- updateAvatarMeshVisibility(imagep->getID(), old_image_id);
- setChanged(TEXTURE);
- if (mDrawable.notNull())
- {
- gPipeline.markTextured(mDrawable);
- }
+ setDiffuseImageAndParams(te, imagep);
}
}
@@ -4909,15 +4963,7 @@ S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image)
if (uuid != getTE(te)->getID() ||
uuid == LLUUID::null)
{
- retval = LLPrimitive::setTETexture(te, uuid);
- LLViewerTexture* baked_texture = getBakedTextureForMagicId(uuid);
- mTEImages[te] = baked_texture ? baked_texture : image;
- updateAvatarMeshVisibility(uuid,old_image_id);
- setChanged(TEXTURE);
- if (mDrawable.notNull())
- {
- gPipeline.markTextured(mDrawable);
- }
+ retval = setDiffuseImageAndParams(te, image);
}
return retval;
}
@@ -5212,6 +5258,29 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
return 0;
}
+ if (pMaterialParams.notNull()
+ && pMaterialParams->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
+ {
+ // Don't update if no alpha is set. If alpha changes, this function will run again,
+ // no point in sheduling additional texture callbacks (in updateDiffuseMatParams)
+ LLTextureEntry* tex_entry = getTE(te);
+ bool is_baked = tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID());
+
+ LLViewerTexture *img_diffuse = getTEImage(te);
+ llassert(NULL != img_diffuse);
+
+ if (NULL != img_diffuse)
+ {
+ // Will modify alpha mask provided to renderer to fit image
+ updateDiffuseMatParams(te, pMaterialParams.get(), img_diffuse, is_baked);
+ }
+ else
+ {
+ LLMaterial *mat = pMaterialParams.get(); // to avoid const
+ mat->setDiffuseFormatPrimary(0);
+ }
+ }
+
retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams);
LL_DEBUGS("Material") << "Changing material params for te " << (S32)te
<< ", object " << mID
@@ -5224,6 +5293,84 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
return retval;
}
+bool LLViewerObject::notifyAboutCreatingTexture(LLViewerTexture *texture)
+{
+ // Confirmation about texture creation, check wait-list
+ // and make changes, or return false
+
+ std::pair<uuid_material_mmap_t::iterator, uuid_material_mmap_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
+
+ bool refresh_materials = false;
+
+ // RGB textures without alpha channels won't work right with alpha,
+ // we provide format to material for material to decide when to drop alpha
+ for (uuid_material_mmap_t::iterator range_it = range.first; range_it != range.second; ++range_it)
+ {
+ LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
+ if (cur_material.notNull()
+ && LLRender::DIFFUSE_MAP == range_it->second.map)
+ {
+ U32 format = texture->getPrimaryFormat();
+ if (format != cur_material->getDiffuseFormatPrimary())
+ {
+ cur_material->setDiffuseFormatPrimary(format);
+ refresh_materials = true;
+ }
+ }
+ } //for
+
+ if (refresh_materials)
+ {
+ LLViewerObject::refreshMaterials();
+ }
+
+ //clear wait-list
+ mWaitingTextureInfo.erase(range.first, range.second);
+
+ return refresh_materials;
+}
+
+bool LLViewerObject::notifyAboutMissingAsset(LLViewerTexture *texture)
+{
+ // When waiting information about texture it turned out to be missing.
+ // Confirm the state, update values accordingly
+ std::pair<uuid_material_mmap_t::iterator, uuid_material_mmap_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
+ if (range.first == range.second) return false;
+
+ bool refresh_materials = false;
+
+ for (uuid_material_mmap_t::iterator range_it = range.first; range_it != range.second; ++range_it)
+ {
+ LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
+ if (cur_material.isNull())
+ continue;
+
+ if (range_it->second.map == LLRender::DIFFUSE_MAP)
+ {
+ LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
+ if (cur_material.notNull()
+ && LLRender::DIFFUSE_MAP == range_it->second.map)
+ {
+ if (0 != cur_material->getDiffuseFormatPrimary())
+ {
+ cur_material->setDiffuseFormatPrimary(0);
+ refresh_materials = true;
+ }
+ }
+ }
+ } //for
+
+ if (refresh_materials)
+ {
+ LLViewerObject::refreshMaterials();
+ }
+
+ //clear wait-list
+ mWaitingTextureInfo.erase(range.first, range.second);
+
+ return refresh_materials;
+}
+
void LLViewerObject::refreshMaterials()
{
setChanged(TEXTURE);