summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2022-10-24 16:26:42 -0500
committerDave Parks <davep@lindenlab.com>2022-10-24 16:26:42 -0500
commit5c86ec6a6130bef9348d6155c6a7404914c20418 (patch)
treebcc13446fda77a997065216d7d36fcb3ae8c28ac /indra
parent554bc6f6b3da2f0949e92e92f09804c8f65b07ca (diff)
SL-18105 Add mechanism for applying overrides that were received before associated ViewerObject was ready to receive them.
Diffstat (limited to 'indra')
-rw-r--r--indra/llprimitive/lltextureentry.cpp11
-rw-r--r--indra/llprimitive/lltextureentry.h4
-rw-r--r--indra/newview/llgltfmateriallist.cpp49
-rw-r--r--indra/newview/llgltfmateriallist.h10
-rw-r--r--indra/newview/llviewerobject.cpp5
-rw-r--r--indra/newview/llvovolume.cpp4
6 files changed, 74 insertions, 9 deletions
diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp
index 68de480d87..d810c6ed25 100644
--- a/indra/llprimitive/lltextureentry.cpp
+++ b/indra/llprimitive/lltextureentry.cpp
@@ -519,6 +519,17 @@ void LLTextureEntry::setGLTFMaterial(LLGLTFMaterial* material)
}
}
+LLGLTFMaterial* LLTextureEntry::getGLTFRenderMaterial() const
+{
+ if (mGLTFRenderMaterial.notNull())
+ {
+ return mGLTFRenderMaterial;
+ }
+
+ llassert(getGLTFMaterialOverride() == nullptr);
+ return getGLTFMaterial();
+}
+
S32 LLTextureEntry::setGLTFRenderMaterial(LLGLTFMaterial* mat)
{
if (mGLTFRenderMaterial != mat)
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index 8dc3434a01..e37bc9a3b6 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -199,12 +199,12 @@ public:
LLGLTFMaterial* getGLTFMaterial() const { return mGLTFMaterial; }
// GLTF override
- LLGLTFMaterial* getGLTFMaterialOverride() { return mGLTFMaterialOverrides; }
+ LLGLTFMaterial* getGLTFMaterialOverride() const { return mGLTFMaterialOverrides; }
void setGLTFMaterialOverride(LLGLTFMaterial* mat) { mGLTFMaterialOverrides = mat; }
// GLTF render material
// nuanced behavior here -- if there is no render material, fall back to getGLTFMaterial, but ONLY for the getter, not the setter
- LLGLTFMaterial* getGLTFRenderMaterial() const { return mGLTFRenderMaterial.notNull() ? mGLTFRenderMaterial.get() : getGLTFMaterial(); }
+ LLGLTFMaterial* getGLTFRenderMaterial() const;
S32 setGLTFRenderMaterial(LLGLTFMaterial* mat);
public:
diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp
index 4861c2a33b..cd60d34d2f 100644
--- a/indra/newview/llgltfmateriallist.cpp
+++ b/indra/newview/llgltfmateriallist.cpp
@@ -43,6 +43,8 @@
#include "json/reader.h"
#include "json/value.h"
+LLGLTFMaterialList gGLTFMaterialList;
+
namespace
{
class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler
@@ -72,24 +74,27 @@ namespace
LL_WARNS() << "LLGLTFMaterialOverrideDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
}
}
+
+ LLUUID object_id = message["object_id"].asUUID();
- LLViewerObject * obj = gObjectList.findObject(message["object_id"].asUUID());
- llassert(obj); // should never get an override for an object we don't know about
+ LLViewerObject * obj = gObjectList.findObject(object_id);
S32 side = message["side"].asInteger();
std::string gltf_json = message["gltf_json"].asString();
std::string warn_msg, error_msg;
LLPointer<LLGLTFMaterial> override_data = new LLGLTFMaterial();
bool success = override_data->fromJSON(gltf_json, warn_msg, error_msg);
+
if (!success)
{
LL_WARNS() << "failed to parse GLTF override data. errors: " << error_msg << " | warnings: " << warn_msg << LL_ENDL;
}
else
{
- if (obj)
+ if (!obj || !obj->setTEGLTFMaterialOverride(side, override_data))
{
- obj->setTEGLTFMaterialOverride(side, override_data);
+ // object not ready to receive override data, queue for later
+ gGLTFMaterialList.queueOverrideUpdate(object_id, side, override_data);
}
}
@@ -99,7 +104,41 @@ namespace
LLGLTFMaterialOverrideDispatchHandler handle_gltf_override_message;
}
-LLGLTFMaterialList gGLTFMaterialList;
+void LLGLTFMaterialList::queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFMaterial* override_data)
+{
+ override_list_t& overrides = mQueuedOverrides[id];
+
+ if (overrides.size() < side + 1)
+ {
+ overrides.resize(side + 1);
+ }
+
+ overrides[side] = override_data;
+}
+
+void LLGLTFMaterialList::applyQueuedOverrides(LLViewerObject* obj)
+{
+ const LLUUID& id = obj->getID();
+ auto& iter = mQueuedOverrides.find(id);
+
+ if (iter != mQueuedOverrides.end())
+ {
+ override_list_t& overrides = iter->second;
+ for (int i = 0; i < overrides.size(); ++i)
+ {
+ if (overrides[i].notNull())
+ {
+ if (!obj->getTE(i)->getGLTFMaterial())
+ { // object doesn't have its base GLTF material yet, don't apply override (yet)
+ return;
+ }
+ obj->setTEGLTFMaterialOverride(i, overrides[i]);
+ }
+ }
+
+ mQueuedOverrides.erase(iter);
+ }
+}
LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id)
{
diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h
index 4b905e32c9..ee32dc8825 100644
--- a/indra/newview/llgltfmateriallist.h
+++ b/indra/newview/llgltfmateriallist.h
@@ -48,10 +48,20 @@ public:
void flushMaterials();
static void registerCallbacks();
+
+ // save an override update for later (for example, if an override arrived for an unknown object)
+ void queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFMaterial* override_data);
+
+ void applyQueuedOverrides(LLViewerObject* obj);
+
private:
typedef std::unordered_map<LLUUID, LLPointer<LLFetchedGLTFMaterial > > uuid_mat_map_t;
uuid_mat_map_t mList;
+ typedef std::vector<LLPointer<LLGLTFMaterial> > override_list_t;
+ typedef std::unordered_map<LLUUID, override_list_t > queued_override_map_t;
+ queued_override_map_t mQueuedOverrides;
+
LLUUID mLastUpdateKey;
};
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 603dcc4fa7..ac519970b7 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -247,6 +247,7 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
LL_WARNS() << "Unknown object pcode " << (S32)pcode << LL_ENDL;
res = NULL; break;
}
+
return res;
}
@@ -5324,8 +5325,8 @@ S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_ma
LLTextureEntry* tep = getTE(te);
if (!tep)
- {
- LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL;
+ { // this could happen if the object is not fully formed yet
+ // returning TEM_CHANGE_NONE here signals to LLGLTFMaterialList to queue the override for later
return retval;
}
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index cb58c173d9..aea4353bc8 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -88,6 +88,7 @@
#include "llcallstack.h"
#include "llsculptidsize.h"
#include "llavatarappearancedefines.h"
+#include "llgltfmateriallist.h"
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
@@ -5823,6 +5824,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
continue;
}
+ // apply any pending material overrides
+ gGLTFMaterialList.applyQueuedOverrides(vobj);
+
std::string vobj_name = llformat("Vol%p", vobj);
bool is_mesh = vobj->isMesh();