SL-20523 Local textures not updating on PBR Materials #2

meow-7.2.2
Andrey Kleshchev 2023-10-27 23:41:13 +03:00 committed by akleshchev
parent dc63dfc0dd
commit 596a63051e
8 changed files with 283 additions and 28 deletions

View File

@ -89,6 +89,11 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
mOverrideDoubleSided = rhs.mOverrideDoubleSided;
mOverrideAlphaMode = rhs.mOverrideAlphaMode;
mLocalTextureIds = rhs.mLocalTextureIds;
mLocalTextureTrackingIds = rhs.mLocalTextureTrackingIds;
updateTextureTracking();
return *this;
}
@ -765,3 +770,44 @@ LLUUID LLGLTFMaterial::getHash() const
return hash;
}
void LLGLTFMaterial::addLocalTextureTracking(const LLUUID& tracking_id, const LLUUID& tex_id)
{
mLocalTextureTrackingIds.insert(tracking_id);
mLocalTextureIds.insert(tex_id);
}
void LLGLTFMaterial::removeLocalTextureTracking(const LLUUID& tracking_id, const LLUUID& tex_id)
{
mLocalTextureTrackingIds.erase(tracking_id);
mLocalTextureIds.erase(tex_id);
}
bool LLGLTFMaterial::replaceLocalTexture(const LLUUID& old_id, const LLUUID& new_id)
{
bool res = false;
for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
if (mTextureId[i] == old_id)
{
mTextureId[i] = new_id;
res = true;
}
}
mLocalTextureIds.erase(old_id);
if (res)
{
mLocalTextureIds.insert(new_id);
}
return res;
}
void LLGLTFMaterial::updateTextureTracking()
{
if (mLocalTextureTrackingIds.size() > 0)
{
LL_WARNS() << "copied a material with local textures, but tracking not implemented" << LL_ENDL;
}
}

View File

@ -223,8 +223,14 @@ public:
virtual void removeTextureEntry(LLTextureEntry* te) {};
// For local textures so that editor will know to track changes
void setHasLocalTextures(bool val) { mHasLocalTextures = val; }
bool hasLocalTextures() { return mHasLocalTextures; }
void addLocalTextureTracking(const LLUUID& tracking_id, const LLUUID &tex_id);
void removeLocalTextureTracking(const LLUUID& tracking_id, const LLUUID& tex_id);
bool hasLocalTextures() { return !mLocalTextureIds.empty(); }
virtual bool replaceLocalTexture(const LLUUID &old_id, const LLUUID& new_id);
virtual void updateTextureTracking();
uuid_set_t mLocalTextureIds;
uuid_set_t mLocalTextureTrackingIds;
protected:
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
@ -242,6 +248,4 @@ protected:
void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const;
template<typename T>
static void writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write = false);
bool mHasLocalTextures;
};

View File

@ -144,6 +144,55 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex)
}
LLViewerFetchedTexture* fetch_texture(const LLUUID& id)
{
LLViewerFetchedTexture* img = nullptr;
if (id.notNull())
{
img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
img->addTextureStats(64.f * 64.f, TRUE);
}
return img;
};
bool LLFetchedGLTFMaterial::replaceLocalTexture(const LLUUID& old_id, const LLUUID& new_id)
{
bool res = false;
if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] == old_id)
{
mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = new_id;
mBaseColorTexture = fetch_texture(new_id);
res = true;
}
if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] == old_id)
{
mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = new_id;
mNormalTexture = fetch_texture(new_id);
res = true;
}
if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] == old_id)
{
mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = new_id;
mMetallicRoughnessTexture = fetch_texture(new_id);
res = true;
}
if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] == old_id)
{
mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = new_id;
mEmissiveTexture = fetch_texture(new_id);
res = true;
}
return res;
}
void LLFetchedGLTFMaterial::updateTextureTracking()
{
for (const LLUUID& id : mLocalTextureTrackingIds)
{
LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(id, this);
}
}
void LLFetchedGLTFMaterial::materialBegin()
{
llassert(!mFetching);

View File

@ -50,6 +50,9 @@ public:
bool isFetching() const { return mFetching; }
virtual bool replaceLocalTexture(const LLUUID& old_id, const LLUUID& new_id) override;
virtual void updateTextureTracking() override;
// Textures used for fetching/rendering
LLPointer<LLViewerFetchedTexture> mBaseColorTexture;
LLPointer<LLViewerFetchedTexture> mNormalTexture;

View File

@ -46,6 +46,7 @@
#include <ctime>
/* misc headers */
#include "llgltfmaterial.h"
#include "llscrolllistctrl.h"
#include "lllocaltextureobject.h"
#include "llviewertexturelist.h"
@ -131,6 +132,14 @@ LLLocalBitmap::~LLLocalBitmap()
LLLocalBitmapMgr::getInstance()->doRebake();
}
for (LLPointer<LLGLTFMaterial> &mat : mGLTFMaterialWithLocalTextures)
{
mat->removeLocalTextureTracking(getTrackingID(), getWorldID());
}
mChangedSignal(getTrackingID(), getWorldID(), LLUUID());
mChangedSignal.disconnect_all_slots();
// delete self from gimagelist
LLViewerFetchedTexture* image = gTextureList.findImage(mWorldID, TEX_LIST_STANDARD);
gTextureList.deleteImage(image);
@ -278,6 +287,17 @@ boost::signals2::connection LLLocalBitmap::setChangedCallback(const LLLocalTextu
return mChangedSignal.connect(cb);
}
void LLLocalBitmap::addGLTFMaterial(LLGLTFMaterial* mat)
{
if (mat
// dupplicate prevention
&& mat->mLocalTextureTrackingIds.find(getTrackingID()) == mat->mLocalTextureTrackingIds.end())
{
mat->addLocalTextureTracking(getTrackingID(), getWorldID());
mGLTFMaterialWithLocalTextures.push_back(mat);
}
}
bool LLLocalBitmap::decodeBitmap(LLPointer<LLImageRaw> rawimg)
{
bool decode_successful = false;
@ -355,7 +375,7 @@ void LLLocalBitmap::replaceIDs(const LLUUID& old_id, LLUUID new_id)
return;
}
mChangedSignal(old_id, new_id);
mChangedSignal(getTrackingID(), old_id, new_id);
// processing updates per channel; makes the process scalable.
// the only actual difference is in SetTE* call i.e. SetTETexture, SetTENormal, etc.
@ -389,8 +409,7 @@ void LLLocalBitmap::replaceIDs(const LLUUID& old_id, LLUUID new_id)
updateUserLayers(old_id, new_id, LLWearableType::WT_UNDERPANTS);
updateUserLayers(old_id, new_id, LLWearableType::WT_UNDERSHIRT);
// Go over any local material
updateGLTFMaterials(old_id, new_id);
}
// this function sorts the faces from a getFaceList[getNumFaces] into a list of objects
@ -588,6 +607,24 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp
}
}
void LLLocalBitmap::updateGLTFMaterials(LLUUID old_id, LLUUID new_id)
{
// Might be a better idea to hold this in LLGLTFMaterialList
for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != mGLTFMaterialWithLocalTextures.end();)
{
if ((*it)->replaceLocalTexture(old_id, new_id))
{
++it;
}
else
{
// matching id not found, no longer in use
(*it)->removeLocalTextureTracking(getTrackingID(), new_id);
it = mGLTFMaterialWithLocalTextures.erase(it);
}
}
}
LLAvatarAppearanceDefines::ETextureIndex LLLocalBitmap::getTexIndex(
LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind)
{
@ -1089,6 +1126,18 @@ boost::signals2::connection LLLocalBitmapMgr::setOnChangedCallback(const LLUUID
return boost::signals2::connection();
}
void LLLocalBitmapMgr::associateGLTFMaterial(const LLUUID tracking_id, LLGLTFMaterial* mat)
{
for (local_list_iter iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++)
{
LLLocalBitmap* unit = *iter;
if (unit->getTrackingID() == tracking_id)
{
unit->addGLTFMaterial(mat);
}
}
}
void LLLocalBitmapMgr::feedScrollList(LLScrollListCtrl* ctrl)
{
if (ctrl)

View File

@ -36,6 +36,7 @@
class LLScrollListCtrl;
class LLImageRaw;
class LLViewerObject;
class LLGLTFMaterial;
class LLLocalBitmap
{
@ -59,10 +60,12 @@ class LLLocalBitmap
bool updateSelf(EUpdateType = UT_REGUPDATE);
typedef boost::signals2::signal<void(const LLUUID& old_id,
typedef boost::signals2::signal<void(const LLUUID& tracking_id,
const LLUUID& old_id,
const LLUUID& new_id)> LLLocalTextureChangedSignal;
typedef LLLocalTextureChangedSignal::slot_type LLLocalTextureCallback;
boost::signals2::connection setChangedCallback(const LLLocalTextureCallback& cb);
void addGLTFMaterial(LLGLTFMaterial* mat);
private: /* self update private section */
bool decodeBitmap(LLPointer<LLImageRaw> raw);
@ -71,6 +74,7 @@ class LLLocalBitmap
void updateUserPrims(LLUUID old_id, LLUUID new_id, U32 channel);
void updateUserVolumes(LLUUID old_id, LLUUID new_id, U32 channel);
void updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type);
void updateGLTFMaterials(LLUUID old_id, LLUUID new_id);
LLAvatarAppearanceDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind);
private: /* private enums */
@ -100,6 +104,11 @@ class LLLocalBitmap
S32 mUpdateRetries;
LLLocalTextureChangedSignal mChangedSignal;
// Store a list of accosiated materials
// Might be a better idea to hold this in LLGLTFMaterialList
typedef std::vector<LLPointer<LLGLTFMaterial> > mat_list_t;
mat_list_t mGLTFMaterialWithLocalTextures;
};
class LLLocalBitmapTimer : public LLEventTimer
@ -130,6 +139,7 @@ public:
bool isLocal(const LLUUID& world_id) const;
std::string getFilename(const LLUUID &tracking_id) const;
boost::signals2::connection setOnChangedCallback(const LLUUID tracking_id, const LLLocalBitmap::LLLocalTextureCallback& cb);
void associateGLTFMaterial(const LLUUID tracking_id, LLGLTFMaterial* mat);
void feedScrollList(LLScrollListCtrl* ctrl);
void doUpdates();

View File

@ -363,6 +363,15 @@ LLMaterialEditor::LLMaterialEditor(const LLSD& key)
}
}
LLMaterialEditor::~LLMaterialEditor()
{
for (mat_connection_map_t::value_type cn : mTextureChangesUpdates)
{
cn.second.mConnection.disconnect();
}
mTextureChangesUpdates.clear();
}
void LLMaterialEditor::setObjectID(const LLUUID& object_id)
{
LLPreview::setObjectID(object_id);
@ -532,11 +541,6 @@ void LLMaterialEditor::onClose(bool app_quitting)
mSelectionUpdateSlot.disconnect();
}
for (boost::signals2::connection& cn : mTextureChangesUpdates)
{
cn.disconnect();
}
LLPreview::onClose(app_quitting);
}
@ -866,7 +870,27 @@ void LLMaterialEditor::setEnableEditing(bool can_modify)
mNormalTextureCtrl->setEnabled(can_modify);
}
void LLMaterialEditor::replaceTexture(const LLUUID& old_id, const LLUUID& new_id)
void LLMaterialEditor::subscribeToLocalTexture(S32 dirty_flag, const LLUUID& tracking_id)
{
LocalTextureConnection info;
info.mTrackingId = tracking_id;
info.mConnection = LLLocalBitmapMgr::getInstance()->setOnChangedCallback(tracking_id,
[this, dirty_flag](const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id)
{
if (new_id.isNull())
{
mTextureChangesUpdates[dirty_flag].mConnection.disconnect();
mTextureChangesUpdates.erase(dirty_flag);
}
else
{
replaceLocalTexture(old_id, new_id);
}
});
mTextureChangesUpdates[dirty_flag] = info;
}
void LLMaterialEditor::replaceLocalTexture(const LLUUID& old_id, const LLUUID& new_id)
{
// todo: might be a good idea to set mBaseColorTextureUploadId here
// and when texturectrl picks a local texture
@ -958,18 +982,17 @@ void LLMaterialEditor::onCommitTexture(LLUICtrl* ctrl, const LLSD& data, S32 dir
childSetValue(upload_fee_ctrl_name, getString("no_upload_fee_string"));
}
// unsubcribe potential old callabck
mat_connection_map_t::iterator found = mTextureChangesUpdates.find(dirty_flag);
if (found != mTextureChangesUpdates.end())
{
found->second.mConnection.disconnect();
}
LLTextureCtrl* tex_ctrl = (LLTextureCtrl*)ctrl;
if (tex_ctrl->isImageLocal())
{
// Theoretically LLSD should be smart enough to not need this, but for extra safety
LLSD key = llsd_clone(getKey());
// Subscribe material editor to local texture updates
mTextureChangesUpdates.push_back(
LLLocalBitmapMgr::getInstance()->setOnChangedCallback(tex_ctrl->getLocalTrackingID(),
[this](const LLUUID &old_id, const LLUUID& new_id)
{
replaceTexture(old_id, new_id);
}));
subscribeToLocalTexture(dirty_flag, tex_ctrl->getLocalTrackingID());
}
}
@ -988,9 +1011,8 @@ void update_local_texture(LLUICtrl* ctrl, LLGLTFMaterial* mat)
LLTextureCtrl* tex_ctrl = (LLTextureCtrl*)ctrl;
if (tex_ctrl->isImageLocal())
{
mat->setHasLocalTextures(true);
// Todo: subscrive material for an update
// tex_ctrl->getLocalTrackingID();
// subscrive material to updates of local textures
LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tex_ctrl->getLocalTrackingID(), mat);
}
}
@ -1465,6 +1487,20 @@ void LLMaterialEditor::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, L
{
me->refreshFromInventory(itemId);
}
if (me && !me->mTextureChangesUpdates.empty())
{
const LLInventoryItem* item = me->getItem();
if (item)
{
// local materials were assigned, force load material and init tracking
LLGLTFMaterial* mat = gGLTFMaterialList.getMaterial(item->getAssetUUID());
for (mat_connection_map_t::value_type val : me->mTextureChangesUpdates)
{
LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.second.mTrackingId, mat);
}
}
}
}
}
@ -1479,6 +1515,16 @@ void LLMaterialEditor::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID
me->setAssetId(newAssetId);
me->refreshFromInventory();
me->setEnabled(true);
if (me && !me->mTextureChangesUpdates.empty())
{
// local materials were assigned, force load material and init tracking
LLGLTFMaterial* mat = gGLTFMaterialList.getMaterial(newAssetId);
for (mat_connection_map_t::value_type val : me->mTextureChangesUpdates)
{
LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.second.mTrackingId, mat);
}
}
}
}
@ -1512,6 +1558,17 @@ void LLMaterialEditor::finishSaveAs(
{
me->loadAsset();
me->setEnabled(true);
// Local texure support
if (!me->mTextureChangesUpdates.empty())
{
// local materials were assigned, force load material and init tracking
LLGLTFMaterial* mat = gGLTFMaterialList.getMaterial(item->getAssetUUID());
for (mat_connection_map_t::value_type val : me->mTextureChangesUpdates)
{
LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.second.mTrackingId, mat);
}
}
}
}
else if(has_unsaved_changes)
@ -2975,6 +3032,34 @@ void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat)
setDoubleSided(mat->mDoubleSided);
setAlphaMode(mat->getAlphaMode());
setAlphaCutoff(mat->mAlphaCutoff);
for (mat_connection_map_t::value_type cn : mTextureChangesUpdates)
{
cn.second.mConnection.disconnect();
}
mTextureChangesUpdates.clear();
for (const LLUUID& tracking_id : mat->mLocalTextureTrackingIds)
{
LLUUID world_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id);
if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR])
{
subscribeToLocalTexture(MATERIAL_BASE_COLOR_TEX_DIRTY, tracking_id);
}
if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS])
{
subscribeToLocalTexture(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY, tracking_id);
}
if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE])
{
subscribeToLocalTexture(MATERIAL_EMISIVE_TEX_DIRTY, tracking_id);
}
if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL])
{
subscribeToLocalTexture(MATERIAL_NORMAL_TEX_DIRTY, tracking_id);
}
}
}
bool LLMaterialEditor::setFromSelection()

View File

@ -87,6 +87,7 @@ protected:
class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
{ public:
LLMaterialEditor(const LLSD& key);
~LLMaterialEditor();
bool setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures = false);
@ -219,7 +220,8 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
void setCanSave(bool value);
void setEnableEditing(bool can_modify);
void replaceTexture(const LLUUID& old_id, const LLUUID& new_id); // Local texture support
void subscribeToLocalTexture(S32 dirty_flag, const LLUUID& tracking_id);
void replaceLocalTexture(const LLUUID& old_id, const LLUUID& new_id); // Local texture support
void onCommitTexture(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag);
void onCancelCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag);
void onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag);
@ -307,6 +309,13 @@ private:
static bool mOverrideInProgress;
static bool mSelectionNeedsUpdate;
boost::signals2::connection mSelectionUpdateSlot;
std::list <boost::signals2::connection> mTextureChangesUpdates;
struct LocalTextureConnection
{
LLUUID mTrackingId;
boost::signals2::connection mConnection;
};
typedef std::map<S32, LocalTextureConnection> mat_connection_map_t;
mat_connection_map_t mTextureChangesUpdates;
};