From 220afbcda0961df86ad08bbd51d96b8c868b2e62 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 2 Jun 2022 18:42:38 -0500 Subject: [PATCH 01/17] SL-17285 Add proper reflection probe support to LLVOVolume, LLPrimitive, and LLPanelVolume --- indra/llprimitive/llprimitive.cpp | 95 +++++++++++ indra/llprimitive/llprimitive.h | 44 +++++ .../class3/deferred/reflectionProbeF.glsl | 21 ++- indra/newview/llpanelvolume.cpp | 100 +++++++++++ indra/newview/llpanelvolume.h | 3 + indra/newview/llreflectionmap.cpp | 51 +++--- indra/newview/llreflectionmap.h | 10 +- indra/newview/llreflectionmapmanager.cpp | 25 +-- indra/newview/lltexturefetch.cpp | 1 + indra/newview/llviewerdisplay.cpp | 1 - indra/newview/llviewerobject.cpp | 5 + indra/newview/llviewerwindow.cpp | 3 +- indra/newview/llviewerwindow.h | 4 +- indra/newview/llvovolume.cpp | 157 +++++++++++++++--- indra/newview/llvovolume.h | 14 ++ .../skins/default/xui/en/floater_tools.xml | 58 ++++++- 16 files changed, 519 insertions(+), 73 deletions(-) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index c46e5fb3c5..87a78eb447 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -81,6 +81,14 @@ const F32 LIGHT_MIN_CUTOFF = 0.0f; const F32 LIGHT_DEFAULT_CUTOFF = 0.0f; const F32 LIGHT_MAX_CUTOFF = 180.f; +// reflection probes +const F32 REFLECTION_PROBE_MIN_AMBIANCE = 0.f; +const F32 REFLECTION_PROBE_MAX_AMBIANCE = 1.f; +const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE = 0.f; +const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE = 0.f; +const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE = 1024.f; +const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE = 0.f; + // "Tension" => [0,10], increments of 0.1 const F32 FLEXIBLE_OBJECT_MIN_TENSION = 0.0f; const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION = 1.0f; @@ -1811,6 +1819,93 @@ bool LLLightParams::fromLLSD(LLSD& sd) //============================================================================ +LLReflectionProbeParams::LLReflectionProbeParams() +{ + mType = PARAMS_REFLECTION_PROBE; +} + +BOOL LLReflectionProbeParams::pack(LLDataPacker& dp) const +{ + dp.packF32(mAmbiance, "ambiance"); + dp.packF32(mClipDistance, "clip_distance"); + dp.packU8(mVolumeType, "volume_type"); + return TRUE; +} + +BOOL LLReflectionProbeParams::unpack(LLDataPacker& dp) +{ + F32 ambiance; + F32 clip_distance; + U8 volume_type; + + dp.unpackF32(ambiance, "ambiance"); + setAmbiance(ambiance); + + dp.unpackF32(clip_distance, "clip_distance"); + setClipDistance(clip_distance); + + dp.unpackU8(volume_type, "volume_type"); + setVolumeType((EInfluenceVolumeType)volume_type); + + return TRUE; +} + +bool LLReflectionProbeParams::operator==(const LLNetworkData& data) const +{ + if (data.mType != PARAMS_REFLECTION_PROBE) + { + return false; + } + const LLReflectionProbeParams* param = (const LLReflectionProbeParams*)&data; + if (param->mAmbiance != mAmbiance) + { + return false; + } + if (param->mClipDistance != mClipDistance) + { + return false; + } + if (param->mVolumeType != mVolumeType) + { + return false; + } + return true; +} + +void LLReflectionProbeParams::copy(const LLNetworkData& data) +{ + const LLReflectionProbeParams* param = (LLReflectionProbeParams*)&data; + mType = param->mType; + mAmbiance = param->mAmbiance; + mClipDistance = param->mClipDistance; + mVolumeType = param->mVolumeType; +} + +LLSD LLReflectionProbeParams::asLLSD() const +{ + LLSD sd; + sd["ambiance"] = getAmbiance(); + sd["clip_distance"] = getClipDistance(); + sd["volume_type"] = getVolumeType(); + return sd; +} + +bool LLReflectionProbeParams::fromLLSD(LLSD& sd) +{ + if (!sd.has("ambiance") || + !sd.has("clip_distance") || + !sd.has("volume_type")) + { + return false; + } + + setAmbiance((F32)sd["ambiance"].asReal()); + setClipDistance((F32)sd["clip_distance"].asReal()); + setVolumeType((EInfluenceVolumeType)sd["volume_type"].asInteger()); + + return true; +} +//============================================================================ LLFlexibleObjectData::LLFlexibleObjectData() { mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS; diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index e23ddd2916..2215133e16 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -108,6 +108,7 @@ public: PARAMS_MESH = 0x60, PARAMS_EXTENDED_MESH = 0x70, PARAMS_RENDER_MATERIAL = 0x80, + PARAMS_REFLECTION_PROBE = 0x90, }; public: @@ -171,6 +172,49 @@ public: F32 getCutoff() const { return mCutoff; } }; +extern const F32 REFLECTION_PROBE_MIN_AMBIANCE; +extern const F32 REFLECTION_PROBE_MAX_AMBIANCE; +extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE; +extern const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE; +extern const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE; +extern const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE; + +class LLReflectionProbeParams : public LLNetworkData +{ +public: + enum EInfluenceVolumeType : U8 + { + VOLUME_TYPE_SPHERE = 0, // use a sphere influence volume + VOLUME_TYPE_BOX = 1, // use a box influence volume + DEFAULT_VOLUME_TYPE = VOLUME_TYPE_SPHERE + }; + +protected: + F32 mAmbiance = REFLECTION_PROBE_DEFAULT_AMBIANCE; + F32 mClipDistance = REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE; + EInfluenceVolumeType mVolumeType = DEFAULT_VOLUME_TYPE; + +public: + LLReflectionProbeParams(); + /*virtual*/ BOOL pack(LLDataPacker& dp) const; + /*virtual*/ BOOL unpack(LLDataPacker& dp); + /*virtual*/ bool operator==(const LLNetworkData& data) const; + /*virtual*/ void copy(const LLNetworkData& data); + // LLSD implementations here are provided by Eddy Stryker. + // NOTE: there are currently unused in protocols + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + void setAmbiance(F32 ambiance) { mAmbiance = llclamp(ambiance, REFLECTION_PROBE_MIN_AMBIANCE, REFLECTION_PROBE_MAX_AMBIANCE); } + void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); } + void setVolumeType(EInfluenceVolumeType type) { mVolumeType = llclamp(type, VOLUME_TYPE_SPHERE, VOLUME_TYPE_BOX); } + + F32 getAmbiance() const { return mAmbiance; } + F32 getClipDistance() const { return mClipDistance; } + EInfluenceVolumeType getVolumeType() const { return mVolumeType; } +}; + //------------------------------------------------- // This structure is also used in the part of the // code that creates new flexible objects. diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 8c1323ba1a..eb9d3f485b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -1,5 +1,5 @@ /** - * @file class2/deferred/reflectionProbeF.glsl + * @file class3/deferred/reflectionProbeF.glsl * * $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code @@ -42,6 +42,8 @@ layout (std140, binding = 1) uniform ReflectionProbes mat4 refBox[REFMAP_COUNT]; // list of bounding spheres for reflection probes sorted by distance to camera (closest first) vec4 refSphere[REFMAP_COUNT]; + // extra parameters (currently only .x used for probe ambiance) + vec4 refParams[REFMAP_COUNT]; // index of cube map in reflectionProbes for a corresponding reflection probe // e.g. cube map channel of refSphere[2] is stored in refIndex[2] // refIndex.x - cubemap channel in reflectionProbes @@ -55,9 +57,6 @@ layout (std140, binding = 1) uniform ReflectionProbes // number of reflection probes present in refSphere int refmapCount; - - // intensity of ambient light from reflection probes - float reflectionAmbiance; }; // Inputs @@ -335,7 +334,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i) } } -vec3 sampleProbes(vec3 pos, vec3 dir, float lod) +vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) { float wsum = 0.0; vec3 col = vec3(0,0,0); @@ -360,7 +359,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod) float atten = 1.0-max(d2-r2, 0.0)/(rr-r2); w *= atten; w *= p; // boost weight based on priority - col += refcol*w; + col += refcol*w*max(minweight, refParams[i].x); wsum += w; } @@ -383,7 +382,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod) float w = 1.0/d2; w *= w; - col += refcol*w; + col += refcol*w*max(minweight, refParams[i].x); wsum += w; } } @@ -399,7 +398,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod) vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod) { - vec3 col = sampleProbes(pos, dir, lod); + vec3 col = sampleProbes(pos, dir, lod, 0.f); //desaturate vec3 hcol = col *0.5; @@ -413,7 +412,7 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod) col *= 0.333333; - return col*reflectionAmbiance; + return col; } @@ -445,12 +444,12 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 l if (glossiness > 0.0) { float lod = (1.0-glossiness)*reflection_lods; - glossenv = sampleProbes(pos, normalize(refnormpersp), lod); + glossenv = sampleProbes(pos, normalize(refnormpersp), lod, 1.f); } if (envIntensity > 0.0) { - legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0); + legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0, 1.f); } } diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 89c558e4f8..e7bbe266e5 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -145,6 +145,16 @@ BOOL LLPanelVolume::postBuild() getChild("Light Ambiance")->setValidateBeforeCommit( precommitValidate); } + // REFLECTION PROBE Parameters + { + childSetCommitCallback("Reflection Probe Checkbox Ctrl", onCommitIsReflectionProbe, this); + childSetCommitCallback("Probe Shape Type Combo Ctrl", onCommitProbe, this); + childSetCommitCallback("Probe Ambiance", onCommitProbe, this); + childSetCommitCallback("Probe Near Clip", onCommitProbe, this); + + + } + // PHYSICS Parameters { // PhysicsShapeType combobox @@ -360,6 +370,40 @@ void LLPanelVolume::getState( ) getChildView("Light Ambiance")->setEnabled(false); } + // Reflection Probe + BOOL is_probe = volobjp && volobjp->getIsReflectionProbe(); + getChild("Reflection Probe Checkbox Ctrl")->setValue(is_probe); + getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); + + bool probe_enabled = is_probe && editable && single_volume; + + getChildView("Probe Volume Type Ctrl")->setEnabled(probe_enabled); + getChildView("Probe Ambiance")->setEnabled(probe_enabled); + getChildView("Probe Near Clip")->setEnabled(probe_enabled); + + if (!probe_enabled) + { + getChild("Probe Volume Type Ctrl", true)->clear(); + getChild("Probe Ambiance", true)->clear(); + getChild("Probe Near Clip", true)->clear(); + } + else + { + std::string volume_type; + if (volobjp->getReflectionProbeVolumeType() == LLReflectionProbeParams::VOLUME_TYPE_BOX) + { + volume_type = "Box"; + } + else + { + volume_type = "Sphere"; + } + + getChild("Probe Volume Type Ctrl", true)->setValue(volume_type); + getChild("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance()); + getChild("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip()); + } + // Animated Mesh BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject(); getChild("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh); @@ -647,6 +691,10 @@ void LLPanelVolume::clearCtrls() getChildView("Light Radius")->setEnabled(false); getChildView("Light Falloff")->setEnabled(false); + getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(false);; + getChildView("Probe Volume Type Ctrl")->setEnabled(false); + getChildView("Probe Ambiance")->setEnabled(false); + getChildView("Probe Near Clip")->setEnabled(false); getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false); getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false); getChildView("FlexNumSections")->setEnabled(false); @@ -684,6 +732,20 @@ void LLPanelVolume::sendIsLight() LL_INFOS() << "update light sent" << LL_ENDL; } +void LLPanelVolume::sendIsReflectionProbe() +{ + LLViewerObject* objectp = mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume* volobjp = (LLVOVolume*)objectp; + + BOOL value = getChild("Reflection Probe Checkbox Ctrl")->getValue(); + volobjp->setIsReflectionProbe(value); + LL_INFOS() << "update reflection probe sent" << LL_ENDL; +} + void LLPanelVolume::sendIsFlexible() { LLViewerObject* objectp = mObject; @@ -927,6 +989,35 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) } +//static +void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) +{ + LLPanelVolume* self = (LLPanelVolume*)userdata; + LLViewerObject* objectp = self->mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume* volobjp = (LLVOVolume*)objectp; + + + volobjp->setReflectionProbeAmbiance((F32)self->getChild("Probe Ambiance")->getValue().asReal()); + volobjp->setReflectionProbeNearClip((F32)self->getChild("Probe Near Clip")->getValue().asReal()); + + std::string shape_type = self->getChild("Probe Volume Type Ctrl")->getValue().asString(); + LLReflectionProbeParams::EInfluenceVolumeType volume_type = LLReflectionProbeParams::DEFAULT_VOLUME_TYPE; + + if (shape_type == "Sphere") + { + volume_type = LLReflectionProbeParams::VOLUME_TYPE_SPHERE; + } + else if (shape_type == "Box") + { + volume_type = LLReflectionProbeParams::VOLUME_TYPE_BOX; + } + volobjp->setReflectionProbeVolumeType(volume_type); +} + // static void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata ) { @@ -949,6 +1040,15 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item } //---------------------------------------------------------------------------- +// static +void LLPanelVolume::onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata) +{ + LLPanelVolume* self = (LLPanelVolume*)userdata; + self->sendIsReflectionProbe(); +} + +//---------------------------------------------------------------------------- + // static void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata ) { diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index 6e49ccb742..16d9ac292d 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -56,12 +56,15 @@ public: void refresh(); void sendIsLight(); + void sendIsReflectionProbe(); void sendIsFlexible(); static bool precommitValidate(const LLSD& data); static void onCommitIsLight( LLUICtrl* ctrl, void* userdata); static void onCommitLight( LLUICtrl* ctrl, void* userdata); + static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata); + static void onCommitProbe(LLUICtrl* ctrl, void* userdata); void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata); static void onCommitFlexible( LLUICtrl* ctrl, void* userdata); void onCommitAnimatedMeshCheckbox(LLUICtrl* ctrl, void* userdata); diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 54a627efd4..f8a2020ccb 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -35,7 +35,6 @@ extern F32SecondsImplicit gFrameTimeSeconds; LLReflectionMap::LLReflectionMap() { - mLastUpdateTime = gFrameTimeSeconds; } void LLReflectionMap::update(U32 resolution, U32 face) @@ -52,7 +51,7 @@ void LLReflectionMap::update(U32 resolution, U32 face) { resolution /= 2; } - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face); + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip()); } bool LLReflectionMap::shouldUpdate() @@ -215,6 +214,35 @@ bool LLReflectionMap::intersects(LLReflectionMap* other) return dist < r2; } +extern LLControlGroup gSavedSettings; + +F32 LLReflectionMap::getAmbiance() +{ + static LLCachedControl minimum_ambiance(gSavedSettings, "RenderReflectionProbeAmbiance", 0.f); + + F32 ret = 0.f; + if (mViewerObject && mViewerObject->getVolume()) + { + ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeAmbiance(); + } + + return llmax(ret, minimum_ambiance()); +} + +F32 LLReflectionMap::getNearClip() +{ + const F32 MINIMUM_NEAR_CLIP = 0.1f; + + F32 ret = 0.f; + + if (mViewerObject && mViewerObject->getVolume()) + { + ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeNearClip(); + } + + return llmax(ret, MINIMUM_NEAR_CLIP); +} + bool LLReflectionMap::getBox(LLMatrix4& box) { if (mViewerObject) @@ -224,25 +252,8 @@ bool LLReflectionMap::getBox(LLMatrix4& box) { LLVOVolume* vobjp = (LLVOVolume*)mViewerObject; - U8 profile = volume->getProfileType(); - U8 path = volume->getPathType(); - - if (profile == LL_PCODE_PROFILE_SQUARE && - path == LL_PCODE_PATH_LINE) + if (vobjp->getReflectionProbeVolumeType() == LLReflectionProbeParams::VOLUME_TYPE_BOX) { - // nope - /*box = vobjp->getRelativeXform(); - box *= vobjp->mDrawable->getRenderMatrix(); - LLMatrix4 modelview(gGLModelView); - box *= modelview; - box.invert();*/ - - // nope - /*box = LLMatrix4(gGLModelView); - box *= vobjp->mDrawable->getRenderMatrix(); - box *= vobjp->getRelativeXform(); - box.invert();*/ - glh::matrix4f mv(gGLModelView); glh::matrix4f scale; LLVector3 s = vobjp->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f)); diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 4f0f124118..a358bf5fdf 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -55,9 +55,15 @@ public: // return true if given Reflection Map's influence volume intersect's with this one's bool intersects(LLReflectionMap* other); + // Get the ambiance value to use for this probe + F32 getAmbiance(); + + // Get the near clip plane distance to use for this probe + F32 getNearClip(); + // get the encoded bounding box of this probe's influence volume - // will only return a box if this probe has a volume with a square - // profile and a linear path + // will only return a box if this probe is associated with a VOVolume + // with its reflection probe influence volume to to VOLUME_TYPE_BOX // return false if no bounding box (treat as sphere influence volume) bool getBox(LLMatrix4& box); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 34055653d4..60396b6c60 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -127,18 +127,12 @@ void LLReflectionMapManager::update() camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); // process kill list - for (int i = 0; i < mProbes.size(); ) + for (auto& probe : mKillList) { - auto& iter = std::find(mKillList.begin(), mKillList.end(), mProbes[i]); - if (iter != mKillList.end()) + auto& iter = std::find(mProbes.begin(), mProbes.end(), probe); + if (iter != mProbes.end()) { - deleteProbe(i); - mProbes.erase(mProbes.begin() + i); - mKillList.erase(iter); - } - else - { - ++i; + deleteProbe(iter - mProbes.begin()); } } @@ -275,7 +269,7 @@ LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* gr { OctreeNode* node = group->getOctreeNode(); F32 size = node->getSize().getF32ptr()[0]; - if (size >= 7.f && size <= 17.f) + if (size >= 15.f && size <= 17.f) { return addProbe(group); } @@ -514,15 +508,15 @@ void LLReflectionMapManager::updateUniforms() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; // structure for packing uniform buffer object - // see class2/deferred/softenLightF.glsl + // see class3/deferred/reflectionProbeF.glsl struct ReflectionProbeData { LLMatrix4 refBox[LL_REFLECTION_PROBE_COUNT]; // object bounding box as needed LLVector4 refSphere[LL_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space + LLVector4 refParams[LL_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance) GLint refIndex[LL_REFLECTION_PROBE_COUNT][4]; GLint refNeighbor[4096]; GLint refmapCount; - GLfloat reflectionAmbiance; }; mReflectionMaps.resize(LL_REFLECTION_PROBE_COUNT); @@ -530,9 +524,6 @@ void LLReflectionMapManager::updateUniforms() ReflectionProbeData rpd; - static LLCachedControl ambiance(gSavedSettings, "RenderReflectionProbeAmbiance", 0.f); - rpd.reflectionAmbiance = ambiance; - // load modelview matrix into matrix 4a LLMatrix4a modelview; modelview.loadu(gGLModelView); @@ -573,6 +564,8 @@ void LLReflectionMapManager::updateUniforms() rpd.refIndex[count][3] = -rpd.refIndex[count][3]; } + rpd.refParams[count].set(refmap->getAmbiance(), 0.f, 0.f, 0.f); + S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors { //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refNeighbors"); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 0edaf40c66..35e4bb03ac 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -3400,6 +3400,7 @@ void LLTextureFetch::sendRequestListToSimulators() gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); } S32 packet = req->mLastPacket + 1; + LL_INFOS() << req->mID << ": " << req->mImagePriority << LL_ENDL; gMessageSystem->nextBlockFast(_PREHASH_RequestImage); gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID); gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mDesiredDiscard); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 1b8e53e667..6d98d9b10e 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1082,7 +1082,6 @@ void display_cube_face() gPipeline.mBackfaceCull = TRUE; - LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE); gViewerWindow->setup3DViewport(); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 6ecf9dd0c4..732beab448 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -6028,6 +6028,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para { new_block = new LLRenderMaterialParams(); break; + } + case LLNetworkData::PARAMS_REFLECTION_PROBE: + { + new_block = new LLReflectionProbeParams(); + break; } default: { diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a6597e3233..6a60671040 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5270,7 +5270,7 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ void display_cube_face(); -BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face) +BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip) { // NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; @@ -5299,6 +5299,7 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea camera->setView(F_PI_BY_TWO); camera->yaw(0.0); camera->setOrigin(origin); + camera->setNear(near_clip); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ac7f8b2e39..c9cf7da8c7 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -368,7 +368,9 @@ public: // origin - vantage point to take the snapshot from // cubearray - cubemap array for storing the results // index - cube index in the array to use (cube index, not face-layer) - BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face); + // face - which cube face to update + // near_clip - near clip setting to use + BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip); // special implementation of simpleSnapshot for reflection maps diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 784c0350fc..6aef9ee7c0 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -985,7 +985,12 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) // Add it to the pipeline mLightSet gPipeline.setLight(mDrawable, TRUE); } - + + if (getIsReflectionProbe()) + { + updateReflectionProbePtr(); + } + updateRadius(); bool force_update = true; // avoid non-alpha mDistance update being optimized away mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); @@ -3496,6 +3501,121 @@ F32 LLVOVolume::getLightCutoff() const } } +void LLVOVolume::setIsReflectionProbe(BOOL is_probe) +{ + BOOL was_probe = getIsReflectionProbe(); + if (is_probe != was_probe) + { + if (is_probe) + { + setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, TRUE, true); + } + else + { + setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, FALSE, true); + } + } + + updateReflectionProbePtr(); +} + +void LLVOVolume::setReflectionProbeAmbiance(F32 ambiance) +{ + LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + if (param_block->getAmbiance() != ambiance) + { + param_block->setAmbiance(ambiance); + parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); + } + } +} + +void LLVOVolume::setReflectionProbeNearClip(F32 near_clip) +{ + LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + if (param_block->getClipDistance() != near_clip) + { + param_block->setClipDistance(near_clip); + parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); + } + } +} + +void LLVOVolume::setReflectionProbeVolumeType(LLReflectionProbeParams::EInfluenceVolumeType volume_type) +{ + LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + if (param_block->getVolumeType() != volume_type) + { + param_block->setVolumeType(volume_type); + parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); + } + } +} + + +BOOL LLVOVolume::getIsReflectionProbe() const +{ + // HACK - make this object a Reflection Probe if a certain UUID is detected + static LLCachedControl reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", ""); + LLUUID probe_id(reflection_probe_id); + + for (U8 i = 0; i < getNumTEs(); ++i) + { + if (getTE(i)->getID() == probe_id) + { + return true; + } + } + // END HACK + + return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); +} + +F32 LLVOVolume::getReflectionProbeAmbiance() const +{ + const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + return param_block->getAmbiance(); + } + else + { + return 0.f; + } +} + +F32 LLVOVolume::getReflectionProbeNearClip() const +{ + const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + return param_block->getClipDistance(); + } + else + { + return 0.f; + } +} + +LLReflectionProbeParams::EInfluenceVolumeType LLVOVolume::getReflectionProbeVolumeType() const +{ + const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + return param_block->getVolumeType(); + } + else + { + return LLReflectionProbeParams::DEFAULT_VOLUME_TYPE; + } +} + U32 LLVOVolume::getVolumeInterfaceID() const { if (mVolumeImpl) @@ -4381,6 +4501,23 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u gPipeline.setLight(mDrawable, is_light); } } + + updateReflectionProbePtr(); +} + +void LLVOVolume::updateReflectionProbePtr() +{ + if (getIsReflectionProbe()) + { + if (mReflectionProbe.isNull()) + { + mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(this); + } + } + else if (mReflectionProbe.notNull()) + { + mReflectionProbe = nullptr; + } } void LLVOVolume::setSelected(BOOL sel) @@ -5690,24 +5827,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool is_pbr = false; #endif - // HACK - make this object a Reflection Probe if a certain UUID is detected - static LLCachedControl reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", ""); - if (facep->getTextureEntry()->getID() == LLUUID(reflection_probe_id)) - { - if (!vobj->mIsReflectionProbe) - { - vobj->mIsReflectionProbe = true; - vobj->mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(vobj); - } - } - else - { - // not a refleciton probe any more - vobj->mIsReflectionProbe = false; - vobj->mReflectionProbe = nullptr; - } - // END HACK - //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render // batch, it will recover its vertex buffer reference from the spatial group facep->setVertexBuffer(NULL); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 4cb7a5481c..93a10781c2 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -178,6 +178,9 @@ public: /*virtual*/ void parameterChanged(U16 param_type, bool local_origin); /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin); + // update mReflectionProbe based on isReflectionProbe() + void updateReflectionProbePtr(); + /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, const EObjectUpdateType update_type, @@ -281,6 +284,17 @@ public: F32 getLightFalloff(const F32 fudge_factor = 1.f) const; F32 getLightCutoff() const; + // Reflection Probes + void setIsReflectionProbe(BOOL is_probe); + void setReflectionProbeAmbiance(F32 ambiance); + void setReflectionProbeNearClip(F32 near_clip); + void setReflectionProbeVolumeType(LLReflectionProbeParams::EInfluenceVolumeType volume_type); + + BOOL getIsReflectionProbe() const; + F32 getReflectionProbeAmbiance() const; + F32 getReflectionProbeNearClip() const; + LLReflectionProbeParams::EInfluenceVolumeType getReflectionProbeVolumeType() const; + // Flexible Objects U32 getVolumeInterfaceID() const; virtual BOOL isFlexible() const; diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 44bdcd86f9..ae4eb64264 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2353,7 +2353,7 @@ even though the user gets a free copy. layout="topleft" left="10" name="Light Intensity" - top_pad="3" + top_delta="32" width="128" /> - + + + + + + + Date: Fri, 3 Jun 2022 10:14:45 -0500 Subject: [PATCH 02/17] SL-17285 Build fix (coding policy needs last line to be blank). --- .../app_settings/shaders/class3/deferred/reflectionProbeF.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index eb9d3f485b..edb78f114b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -472,4 +472,4 @@ void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 no fresnel = min(fresnel+envIntensity, 1.0); reflected_color *= (envIntensity*fresnel)*brighten(spec.rgb); color = mix(color.rgb, reflected_color, envIntensity); - } \ No newline at end of file + } From a185fae28d7e035226d4b5f7c350f94830001b06 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 3 Jun 2022 11:36:37 -0500 Subject: [PATCH 03/17] SL-17285 Build fix take two. --- indra/llprimitive/llprimitive.cpp | 2 +- .../app_settings/shaders/class3/deferred/reflectionProbeF.glsl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 87a78eb447..6044048d09 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1886,7 +1886,7 @@ LLSD LLReflectionProbeParams::asLLSD() const LLSD sd; sd["ambiance"] = getAmbiance(); sd["clip_distance"] = getClipDistance(); - sd["volume_type"] = getVolumeType(); + sd["volume_type"] = (U8) getVolumeType(); return sd; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index edb78f114b..3fd001e7f5 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -473,3 +473,4 @@ void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 no reflected_color *= (envIntensity*fresnel)*brighten(spec.rgb); color = mix(color.rgb, reflected_color, envIntensity); } + From 0837b65fdd2ea7f50f47209bd8f1109968a677fb Mon Sep 17 00:00:00 2001 From: Ptolemy Date: Tue, 7 Jun 2022 16:14:54 -0700 Subject: [PATCH 04/17] DRTVWR-559: Fix fullbrightShiny not compiling on AMD due to type mismatch --- .../shaders/class1/deferred/fullbrightShinyF.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl index 9fcee04c32..f693323d45 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl @@ -38,7 +38,7 @@ uniform sampler2D diffuseMap; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; VARYING vec3 vary_texcoord1; -VARYING vec4 vary_position; +VARYING vec3 vary_position; uniform samplerCube environmentMap; @@ -74,7 +74,7 @@ void main() vec3 amblit; vec3 additive; vec3 atten; - vec3 pos = vary_position.xyz/vary_position.w; + vec3 pos = vary_position.xyz; calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false); From 8c0163bcb48df56112a625550d411741c20c5846 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Wed, 13 Apr 2022 12:32:58 -0600 Subject: [PATCH 05/17] SL-17214 initial loader class skeleton --- indra/llmath/v4color.h | 12 +- indra/llprimitive/CMakeLists.txt | 2 + indra/llprimitive/lldaeloader.cpp | 26 +- indra/llprimitive/lldaeloader.h | 2 +- indra/llprimitive/llgltfloader.cpp | 336 ++++++++++++++++++++++++ indra/llprimitive/llgltfloader.h | 207 +++++++++++++++ indra/llprimitive/llmodelloader.cpp | 13 +- indra/newview/llfilepicker.cpp | 54 ++-- indra/newview/llfilepicker.h | 8 +- indra/newview/llfloatermodelpreview.cpp | 2 +- indra/newview/llmodelpreview.cpp | 50 +++- indra/newview/llviewermenu.cpp | 5 - indra/newview/llviewermenufile.cpp | 7 - 13 files changed, 640 insertions(+), 84 deletions(-) create mode 100644 indra/llprimitive/llgltfloader.cpp create mode 100644 indra/llprimitive/llgltfloader.h diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 175edf1471..f2863be531 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -88,7 +88,8 @@ class LLColor4 const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha) const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec - const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled. + const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec + const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled. const LLColor4& setAlpha(F32 a); @@ -334,6 +335,15 @@ inline const LLColor4& LLColor4::set(const F32 *vec) return (*this); } +inline const LLColor4& LLColor4::set(const F64 *vec) +{ + mV[VX] = static_cast(vec[VX]); + mV[VY] = static_cast(vec[VY]); + mV[VZ] = static_cast(vec[VZ]); + mV[VW] = static_cast(vec[VW]); + return (*this); +} + // deprecated inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z) { diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index fff4d8ef0a..9d75dab31e 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -28,6 +28,7 @@ include_directories(SYSTEM set(llprimitive_SOURCE_FILES lldaeloader.cpp + llgltfloader.cpp llmaterialid.cpp llmaterial.cpp llmaterialtable.cpp @@ -46,6 +47,7 @@ set(llprimitive_SOURCE_FILES set(llprimitive_HEADER_FILES CMakeLists.txt lldaeloader.h + llgltfloader.h legacy_object_types.h llmaterial.h llmaterialid.h diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index e89690438e..94f8500dab 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -2504,19 +2504,19 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD& return (status == LLModel::NO_ERRORS); } -//static -LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh) -{ - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - LLModel* ret = new LLModel(volume_params, 0.f); - createVolumeFacesFromDomMesh(ret, mesh); - if (ret->mLabel.empty()) - { - ret->mLabel = getElementLabel(mesh); - } - return ret; -} +////static +//LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh) +//{ +// LLVolumeParams volume_params; +// volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); +// LLModel* ret = new LLModel(volume_params, 0.f); +// createVolumeFacesFromDomMesh(ret, mesh); +// if (ret->mLabel.empty()) +// { +// ret->mLabel = getElementLabel(mesh); +// } +// return ret; +//} //static diff version supports creating multiple models when material counts spill // over the 8 face server-side limit diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h index 2b211343e1..9e80980ddf 100644 --- a/indra/llprimitive/lldaeloader.h +++ b/indra/llprimitive/lldaeloader.h @@ -92,7 +92,7 @@ protected: static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh, LLSD& log_msg); static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh); - static LLModel* loadModelFromDomMesh(domMesh* mesh); + //static LLModel* loadModelFromDomMesh(domMesh* mesh); // Loads a mesh breaking it into one or more models as necessary // to get around volume face limitations while retaining >8 materials diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp new file mode 100644 index 0000000000..001623ac9e --- /dev/null +++ b/indra/llprimitive/llgltfloader.cpp @@ -0,0 +1,336 @@ +/** + * @file LLGLTFLoader.cpp + * @brief LLGLTFLoader class implementation + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "LLGLTFLoader.h" + +// Import & define single-header gltf import/export lib +#define TINYGLTF_IMPLEMENTATION +#define TINYGLTF_USE_CPP14 // default is C++ 11 + +// tinygltf by default loads image files using STB +#define STB_IMAGE_IMPLEMENTATION +// to use our own image loading: +// 1. replace this definition with TINYGLTF_NO_STB_IMAGE +// 2. provide image loader callback with TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data) + +// tinygltf saves image files using STB +#define STB_IMAGE_WRITE_IMPLEMENTATION +// similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and TinyGLTF::SetImageWriter(fxn, data) + +// Additionally, disable inclusion of STB header files entirely with +// TINYGLTF_NO_INCLUDE_STB_IMAGE +// TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE +#include "tinygltf\tiny_gltf.h" + +#include + +#include "llsdserialize.h" +#include "lljoint.h" + +#include "glh/glh_linear.h" +#include "llmatrix4a.h" + +#include +#include + +static const std::string lod_suffix[LLModel::NUM_LODS] = +{ + "_LOD0", + "_LOD1", + "_LOD2", + "", + "_PHYS", +}; + +const U32 LIMIT_MATERIALS_OUTPUT = 12; + +LLGLTFLoader::LLGLTFLoader(std::string filename, + S32 lod, + LLModelLoader::load_callback_t load_cb, + LLModelLoader::joint_lookup_func_t joint_lookup_func, + LLModelLoader::texture_load_func_t texture_load_func, + LLModelLoader::state_callback_t state_cb, + void * opaque_userdata, + JointTransformMap & jointTransformMap, + JointNameSet & jointsFromNodes, + std::map &jointAliasMap, + U32 maxJointsPerMesh, + U32 modelLimit) //, + //bool preprocess) + : LLModelLoader( filename, + lod, + load_cb, + joint_lookup_func, + texture_load_func, + state_cb, + opaque_userdata, + jointTransformMap, + jointsFromNodes, + jointAliasMap, + maxJointsPerMesh ), + mGeneratedModelLimit(modelLimit), + //mPreprocessGLTF(preprocess), + mMeshesLoaded(false), + mMaterialsLoaded(false) +{ +} + +LLGLTFLoader::~LLGLTFLoader() {} + +bool LLGLTFLoader::OpenFile(const std::string &filename) +{ + tinygltf::TinyGLTF loader; + std::string error_msg; + std::string warn_msg; + + // Load a tinygltf model fom a file. Assumes that the input filename has already been + // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish. + if (std::string::npos == filename.rfind(".gltf")) + { // file is binary + mGltfLoaded = loader.LoadBinaryFromFile(&mGltfModel, &error_msg, &warn_msg, filename); + } + else + { // file is ascii + mGltfLoaded = loader.LoadASCIIFromFile(&mGltfModel, &error_msg, &warn_msg, filename); + } + + if (!mGltfLoaded) + { + if (!warn_msg.empty()) + LL_WARNS() << "gltf load warning: " << warn_msg.c_str() << LL_ENDL; + if (!error_msg.empty()) + LL_WARNS() << "gltf load error: " << error_msg.c_str() << LL_ENDL; + return false; + } + + mMeshesLoaded = parseMeshes(); + if (mMeshesLoaded) uploadMeshes(); + + mMaterialsLoaded = parseMaterials(); + if (mMaterialsLoaded) uploadMaterials(); + + return (mMeshesLoaded || mMaterialsLoaded); +} + +bool LLGLTFLoader::parseMeshes() +{ + if (!mGltfLoaded) return false; + + // 2022-04 DJH Volume params from dae example. TODO understand PCODE + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + for (tinygltf::Mesh mesh : mGltfModel.meshes) + { + LLModel *pModel = new LLModel(volume_params, 0.f); + + if (populateModelFromMesh(pModel, mesh) && + (LLModel::NO_ERRORS == pModel->getStatus()) && + validate_model(pModel)) + { + mModelList.push_back(pModel); + } + else + { + setLoadState(ERROR_MODEL + pModel->getStatus()); + delete(pModel); + return false; + } + } + return true; +} + +bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh) +{ + pModel->mLabel = mesh.name; + int pos_idx, norm_idx, tan_idx, uv0_idx, uv1_idx, color0_idx, color1_idx; + tinygltf::Accessor indices_a, positions_a, normals_a, uv0_a, color0_a; + + auto prims = mesh.primitives; + for (auto prim : prims) + { + if (prim.indices >= 0) indices_a = mGltfModel.accessors[prim.indices]; + + pos_idx = (prim.attributes.count("POSITION") > 0) ? prim.attributes.at("POSITION") : -1; + if (pos_idx >= 0) + { + positions_a = mGltfModel.accessors[pos_idx]; + if (TINYGLTF_COMPONENT_TYPE_FLOAT != positions_a.componentType) + continue; + auto positions_bv = mGltfModel.bufferViews[positions_a.bufferView]; + auto positions_buf = mGltfModel.buffers[positions_bv.buffer]; + //auto type = positions_vb. + //if (positions_buf.name + } + + norm_idx = (prim.attributes.count("NORMAL") > 0) ? prim.attributes.at("NORMAL") : -1; + tan_idx = (prim.attributes.count("TANGENT") > 0) ? prim.attributes.at("TANGENT") : -1; + uv0_idx = (prim.attributes.count("TEXCOORDS_0") > 0) ? prim.attributes.at("TEXCOORDS_0") : -1; + uv1_idx = (prim.attributes.count("TEXCOORDS_1") > 0) ? prim.attributes.at("TEXCOORDS_1") : -1; + color0_idx = (prim.attributes.count("COLOR_0") > 0) ? prim.attributes.at("COLOR_0") : -1; + color1_idx = (prim.attributes.count("COLOR_1") > 0) ? prim.attributes.at("COLOR_1") : -1; + + if (prim.mode == TINYGLTF_MODE_TRIANGLES) + { + //auto pos = mesh. TODO resume here DJH 2022-04 + } + } + + //pModel->addFace() + return false; +} + +bool LLGLTFLoader::parseMaterials() +{ + if (!mGltfLoaded) return false; + + // fill local texture data structures + mSamplers.clear(); + for (auto in_sampler : mGltfModel.samplers) + { + gltf_sampler sampler{ 0 }; + sampler.magFilter = in_sampler.magFilter; + sampler.minFilter = in_sampler.minFilter; + sampler.wrapS = in_sampler.wrapS; + sampler.wrapT = in_sampler.wrapT; + sampler.name = in_sampler.name; // unused + mSamplers.push_back(sampler); + } + + mImages.clear(); + for (auto in_image : mGltfModel.images) + { + gltf_image image{ 0 }; + image.numChannels = in_image.component; + image.bytesPerChannel = in_image.bits >> 3; + image.pixelType = in_image.pixel_type; + image.size = in_image.image.size(); + image.height = in_image.height; + image.width = in_image.width; + image.data = in_image.image.data(); + + if (in_image.as_is) + { + LL_WARNS("GLTF_IMPORT") << "Unsupported image encoding" << LL_ENDL; + return false; + } + + if (image.size != image.height * image.width * image.numChannels * image.bytesPerChannel) + { + LL_WARNS("GLTF_IMPORT") << "Image size error" << LL_ENDL; + return false; + } + + mImages.push_back(image); + } + + mTextures.clear(); + for (auto in_tex : mGltfModel.textures) + { + gltf_texture tex{ 0 }; + tex.image_idx = in_tex.source; + tex.sampler_idx = in_tex.sampler; + + if (tex.image_idx >= mImages.size() || tex.sampler_idx >= mSamplers.size()) + { + LL_WARNS("GLTF_IMPORT") << "Texture sampler/image index error" << LL_ENDL; + return false; + } + + mTextures.push_back(tex); + } + + // parse each material + for (tinygltf::Material gltf_material : mGltfModel.materials) + { + gltf_render_material mat{ 0 }; + mat.name = gltf_material.name; + + mat.normalScale = gltf_material.normalTexture.scale; + mat.normalTexIdx = gltf_material.normalTexture.index; + mat.normalTexCoordIdx = gltf_material.normalTexture.texCoord; + + mat.occlusionScale = gltf_material.occlusionTexture.strength; + mat.occlusionTexIdx = gltf_material.occlusionTexture.index; + mat.occlusionTexCoordIdx = gltf_material.occlusionTexture.texCoord; + + mat.emissiveColor.set(gltf_material.emissiveFactor.data()); + mat.emissiveColorTexIdx = gltf_material.emissiveTexture.index; + mat.emissiveColorTexCoordIdx = gltf_material.emissiveTexture.texCoord; + + mat.alphaMode = gltf_material.alphaMode; + mat.alphaMask = gltf_material.alphaCutoff; + + tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness; + mat.hasPBR = true; + + mat.pbr.baseColor.set(pbr.baseColorFactor.data()); + mat.pbr.baseColorTexIdx = pbr.baseColorTexture.index; + mat.pbr.baseColorTexCoordIdx = pbr.baseColorTexture.texCoord; + + mat.pbr.metalness = pbr.metallicFactor; + mat.pbr.roughness = pbr.roughnessFactor; + mat.pbr.metalRoughTexIdx = pbr.metallicRoughnessTexture.index; + mat.pbr.metalRoughTexCoordIdx = pbr.metallicRoughnessTexture.texCoord; + + if (mat.normalTexIdx >= mTextures.size() || + mat.occlusionTexIdx >= mTextures.size() || + mat.emissiveColorTexIdx >= mTextures.size() || + mat.pbr.baseColorTexIdx >= mTextures.size() || + mat.pbr.metalRoughTexIdx >= mTextures.size()) + { + LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL; + return false; + } + + if (mat.normalTexCoordIdx > 0 || // May have to loosen this condition + mat.occlusionTexCoordIdx > 0 || + mat.emissiveColorTexCoordIdx > 0 || + mat.pbr.baseColorTexCoordIdx > 0 || + mat.pbr.metalRoughTexCoordIdx > 0) + { + LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL; + return false; + } + + mMaterials.push_back(mat); + } + + return true; +} + +// TODO: convert raw vertex buffers to UUIDs +void LLGLTFLoader::uploadMeshes() +{ + llassert(0); +} + +// TODO: convert raw index buffers to UUIDs +void LLGLTFLoader::uploadMaterials() +{ + llassert(0); +} + diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h new file mode 100644 index 0000000000..9bffeef4ab --- /dev/null +++ b/indra/llprimitive/llgltfloader.h @@ -0,0 +1,207 @@ +/** + * @file LLGLTFLoader.h + * @brief LLGLTFLoader class definition + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLGLTFLoader_H +#define LL_LLGLTFLoader_H + +#include "tinygltf\tiny_gltf.h" + +#include "llmodelloader.h" + +typedef struct // gltf sampler +{ // Uses GL enums + S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR + S32 magFilter; // GL_NEAREST or GL_LINEAR + S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT + S32 wrapT; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT + //S32 wrapR; // seen in some sample files, but not part of glTF 2.0 spec. Ignored. + std::string name; // optional, currently unused + // extensions and extras are sampler optional fields that we don't support - at least initially +} gltf_sampler; + +typedef struct // gltf image +{ // Note that glTF images are defined with row 0 at the top + U8* data; // ptr to decoded image data + U32 size; // in bytes, regardless of channel width + U32 width; + U32 height; + U32 numChannels; // range 1..4 + U32 bytesPerChannel; // converted from gltf "bits", expects only 8, 16 or 32 as input + U32 pixelType; // one of (TINYGLTF_COMPONENT_TYPE)_UNSIGNED_BYTE, _UNSIGNED_SHORT, _UNSIGNED_INT, or _FLOAT +} gltf_image; + +typedef struct // texture +{ + U32 image_idx; + U32 sampler_idx; +} gltf_texture; + + +// TODO: 2022-05 DJH add UUIDs for each texture +typedef struct // gltf_pbrMR_material +{ + // scalar values + LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present. + double metalness; + double roughness; + + // textures + U32 baseColorTexIdx; // always sRGB encoded + U32 baseColorTexCoordIdx; + + U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel + U32 metalRoughTexCoordIdx; +} gltf_pbr; + +typedef struct // render material +{ + std::string name; + + // scalar values + double normalScale; // scale applies only to X,Y components of normal + double occlusionScale; // strength multiplier for occlusion + LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent) + std::string alphaMode; // "OPAQUE", "MASK" or "BLEND" + double alphaMask; + + // textures + U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0) + U32 normalTexCoordIdx; + + U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded + U32 occlusionTexCoordIdx; + + U32 emissiveColorTexIdx; // always stored as sRGB, in nits (candela / meter^2) + U32 emissiveColorTexCoordIdx; + + // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry?? + + bool hasPBR; + gltf_pbr pbr; + +} gltf_render_material; + +typedef struct // gltf_mesh +{ + std::string name; + + // TODO DJH 2022-04 + +} gltf_mesh; + +class LLGLTFLoader : public LLModelLoader +{ + public: + typedef std::map material_map; + typedef void gltfElement; // TBD + typedef void GLTF; // TBD + + // typedef std::map > > gltf_model_map; + // gltf_model_map mModelsMap; + + LLGLTFLoader(std::string filename, + S32 lod, + LLModelLoader::load_callback_t load_cb, + LLModelLoader::joint_lookup_func_t joint_lookup_func, + LLModelLoader::texture_load_func_t texture_load_func, + LLModelLoader::state_callback_t state_cb, + void * opaque_userdata, + JointTransformMap & jointTransformMap, + JointNameSet & jointsFromNodes, + std::map &jointAliasMap, + U32 maxJointsPerMesh, + U32 modelLimit); //, + //bool preprocess ); + virtual ~LLGLTFLoader(); + + virtual bool OpenFile(const std::string &filename); + +protected: + tinygltf::Model mGltfModel; + bool mGltfLoaded; + bool mMeshesLoaded; + bool mMaterialsLoaded; + + std::vector mMeshes; + std::vector mMaterials; + + std::vector mTextures; + std::vector mImages; + std::vector mSamplers; + +private: + U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels +// bool mPreprocessGLTF; + + bool parseMeshes(); + void uploadMeshes(); + bool parseMaterials(); + void uploadMaterials(); + bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh); + + /* + void processElement(gltfElement *element, bool &badElement, GLTF *gltf); + void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin); + + material_map getMaterials(LLModel *model, gltfInstance_geometry *instance_geo, GLTF *gltf); + LLImportMaterial profileToMaterial(gltfProfile_COMMON *material, GLTF *gltf); + LLColor4 getGltfColor(gltfElement *element); + + gltfElement *getChildFromElement(gltfElement *pElement, std::string const &name); + + bool isNodeAJoint(gltfNode *pNode); + void processJointNode(gltfNode *pNode, std::map &jointTransforms); + void extractTranslation(gltfTranslate *pTranslate, LLMatrix4 &transform); + void extractTranslationViaElement(gltfElement *pTranslateElement, LLMatrix4 &transform); + void extractTranslationViaSID(gltfElement *pElement, LLMatrix4 &transform); + void buildJointToNodeMappingFromScene(gltfElement *pRoot); + void processJointToNodeMapping(gltfNode *pNode); + void processChildJoints(gltfNode *pParentNode); + + bool verifyCount(int expected, int result); + + // Verify that a controller matches vertex counts + bool verifyController(gltfController *pController); + + static bool addVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh, LLSD &log_msg); + static bool createVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh); + + static LLModel *loadModelFromGltfMesh(gltfMesh *mesh); + + // Loads a mesh breaking it into one or more models as necessary + // to get around volume face limitations while retaining >8 materials + // + bool loadModelsFromGltfMesh(gltfMesh *mesh, std::vector &models_out, U32 submodel_limit); + + static std::string getElementLabel(gltfElement *element); + static size_t getSuffixPosition(std::string label); + static std::string getLodlessLabel(gltfElement *element); + + static std::string preprocessGLTF(std::string filename); + */ + +}; +#endif // LL_LLGLTFLLOADER_H diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index 5171621007..554ed54de1 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -160,7 +160,8 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin std::string::size_type i = model_filename.rfind("."); if (i != std::string::npos) { - slm_filename.replace(i, model_filename.size()-1, ".slm"); + slm_filename.resize(i, '\0'); + slm_filename.append(".slm"); return true; } else @@ -172,7 +173,7 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin bool LLModelLoader::doLoadModel() { //first, look for a .slm file of the same name that was modified later - //than the .dae + //than the specified model file if (mTrySLM) { @@ -182,13 +183,13 @@ bool LLModelLoader::doLoadModel() llstat slm_status; if (LLFile::stat(slm_filename, &slm_status) == 0) { //slm file exists - llstat dae_status; - if (LLFile::stat(mFilename, &dae_status) != 0 || - dae_status.st_mtime < slm_status.st_mtime) + llstat model_file_status; + if (LLFile::stat(mFilename, &model_file_status) != 0 || + model_file_status.st_mtime < slm_status.st_mtime) { if (loadFromSLM(slm_filename)) { //slm successfully loaded, if this fails, fall through and - //try loading from dae + //try loading from model file mLod = -1; //successfully loading from an slm implicitly sets all //LoDs diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 3669fb1eeb..4e2cc34207 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -55,13 +55,11 @@ LLFilePicker LLFilePicker::sInstance; #define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" #define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0" #define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0" -#ifdef _CORY_TESTING -#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0" -#endif +#define GLTF_FILTER L"glTF (*.gltf; *.glb)\0*.gltf;*.glb\0" #define XML_FILTER L"XML files (*.xml)\0*.xml\0" #define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0" #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" -#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0" +#define MODEL_FILTER L"Model files (*.dae; *.gltf; *.glb)\0*.dae;*.gltf;*.glb\0" #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0" #define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0" #endif @@ -193,16 +191,14 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = ANIM_FILTER \ L"\0"; break; - case FFLOAD_COLLADA: + case FFLOAD_GLTF: + mOFN.lpstrFilter = GLTF_FILTER \ + L"\0"; + break; + case FFLOAD_COLLADA: mOFN.lpstrFilter = COLLADA_FILTER \ L"\0"; break; -#ifdef _CORY_TESTING - case FFLOAD_GEOMETRY: - mOFN.lpstrFilter = GEOMETRY_FILTER \ - L"\0"; - break; -#endif case FFLOAD_XML: mOFN.lpstrFilter = XML_FILTER \ L"\0"; @@ -480,18 +476,16 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, L"XAF Anim File (*.xaf)\0*.xaf\0" \ L"\0"; break; -#ifdef _CORY_TESTING - case FFSAVE_GEOMETRY: + case FFSAVE_GLTF: if (filename.empty()) { - wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + wcsncpy( mFilesW,L"untitled.glb", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } - mOFN.lpstrDefExt = L"slg"; + mOFN.lpstrDefExt = L"glb"; mOFN.lpstrFilter = - L"SLG SL Geometry File (*.slg)\0*.slg\0" \ + L"glTF Asset File (*.gltf *.glb)\0*.gltf;*.glb\0" \ L"\0"; break; -#endif case FFSAVE_XML: if (filename.empty()) { @@ -621,14 +615,13 @@ std::vector* LLFilePicker::navOpenFilterProc(ELoadFilter filter) // allowedv->push_back("bvh"); allowedv->push_back("anim"); break; + case FFLOAD_GLTF: + allowedv->push_back("gltf"); + allowedv->push_back("glb"); + break; case FFLOAD_COLLADA: allowedv->push_back("dae"); break; -#ifdef _CORY_TESTING - case FFLOAD_GEOMETRY: - allowedv->push_back("slg"); - break; -#endif case FFLOAD_XML: allowedv->push_back("xml"); break; @@ -728,13 +721,11 @@ bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena extension = "xaf"; break; -#ifdef _CORY_TESTING - case FFSAVE_GEOMETRY: + case FFSAVE_GLTF: type = "\?\?\?\?"; creator = "\?\?\?\?"; - extension = "slg"; + extension = "glb"; break; -#endif case FFSAVE_XML: type = "\?\?\?\?"; @@ -1354,10 +1345,13 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) case FFLOAD_XML: filtername = add_xml_filter_to_gtkchooser(picker); break; - case FFLOAD_COLLADA: - filtername = add_collada_filter_to_gtkchooser(picker); - break; - case FFLOAD_IMAGE: + case FFLOAD_GLTF: + filtername = dead_code_should_blow_up_here(picker); + break; + case FFLOAD_COLLADA: + filtername = add_collada_filter_to_gtkchooser(picker); + break; + case FFLOAD_IMAGE: filtername = add_imageload_filter_to_gtkchooser(picker); break; case FFLOAD_SCRIPT: diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 04ba4416d7..a314207da6 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -77,9 +77,7 @@ public: FFLOAD_WAV = 2, FFLOAD_IMAGE = 3, FFLOAD_ANIM = 4, -#ifdef _CORY_TESTING - FFLOAD_GEOMETRY = 5, -#endif + FFLOAD_GLTF = 5, FFLOAD_XML = 6, FFLOAD_SLOBJECT = 7, FFLOAD_RAW = 8, @@ -99,9 +97,7 @@ public: FFSAVE_BMP = 5, FFSAVE_AVI = 6, FFSAVE_ANIM = 7, -#ifdef _CORY_TESTING - FFSAVE_GEOMETRY = 8, -#endif + FFSAVE_GLTF = 8, FFSAVE_XML = 9, FFSAVE_COLLADA = 10, FFSAVE_RAW = 11, diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 7279e1ad6d..b77341f806 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -97,7 +97,7 @@ private: }; LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod) -: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA) +: LLFilePickerThread(LLFilePicker::FFLOAD_MODEL) { mMP = mp; mLOD = lod; diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 859d987fc3..e67bd6468e 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -30,6 +30,7 @@ #include "llmodelloader.h" #include "lldaeloader.h" +#include "llgltfloader.h" #include "llfloatermodelpreview.h" #include "llagent.h" @@ -732,20 +733,41 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable std::map joint_alias_map; getJointAliases(joint_alias_map); - mModelLoader = new LLDAELoader( - filename, - lod, - &LLModelPreview::loadedCallback, - &LLModelPreview::lookupJointByName, - &LLModelPreview::loadTextures, - &LLModelPreview::stateChangedCallback, - this, - mJointTransformMap, - mJointsFromNode, - joint_alias_map, - LLSkinningUtil::getMaxJointCount(), - gSavedSettings.getU32("ImporterModelLimit"), - gSavedSettings.getBOOL("ImporterPreprocessDAE")); + // three possible file extensions, .dae .gltf .glb + // check for .dae and if not then assume one of the .gl?? + if (std::string::npos != filename.rfind(".dae")) + { + mModelLoader = new LLDAELoader( + filename, + lod, + &LLModelPreview::loadedCallback, + &LLModelPreview::lookupJointByName, + &LLModelPreview::loadTextures, + &LLModelPreview::stateChangedCallback, + this, + mJointTransformMap, + mJointsFromNode, + joint_alias_map, + LLSkinningUtil::getMaxJointCount(), + gSavedSettings.getU32("ImporterModelLimit"), + gSavedSettings.getBOOL("ImporterPreprocessDAE")); + } + else + { + mModelLoader = new LLGLTFLoader( + filename, + lod, + &LLModelPreview::loadedCallback, + &LLModelPreview::lookupJointByName, + &LLModelPreview::loadTextures, + &LLModelPreview::stateChangedCallback, + this, + mJointTransformMap, + mJointsFromNode, + joint_alias_map, + LLSkinningUtil::getMaxJointCount(), + gSavedSettings.getU32("ImporterModelLimit")); + } if (force_disable_slm) { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 8732bde35c..9c8a666185 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -267,16 +267,11 @@ void handle_reset_view(); void handle_duplicate_in_place(void*); - void handle_object_owner_self(void*); void handle_object_owner_permissive(void*); void handle_object_lock(void*); void handle_object_asset_ids(void*); void force_take_copy(void*); -#ifdef _CORY_TESTING -void force_export_copy(void*); -void force_import_geometry(void*); -#endif void handle_force_parcel_owner_to_me(void*); void handle_force_parcel_to_content(void*); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 28ff69eaf5..32fdfe282d 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -277,9 +277,6 @@ void LLMediaFilePicker::notify(const std::vector& filenames) static std::string SOUND_EXTENSIONS = "wav"; static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png"; static std::string ANIM_EXTENSIONS = "bvh anim"; -#ifdef _CORY_TESTING -static std::string GEOMETRY_EXTENSIONS = "slg"; -#endif static std::string XML_EXTENSIONS = "xml"; static std::string SLOBJECT_EXTENSIONS = "slobject"; #endif @@ -301,10 +298,6 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter) return SLOBJECT_EXTENSIONS; case LLFilePicker::FFLOAD_MODEL: return MODEL_EXTENSIONS; -#ifdef _CORY_TESTING - case LLFilePicker::FFLOAD_GEOMETRY: - return GEOMETRY_EXTENSIONS; -#endif case LLFilePicker::FFLOAD_XML: return XML_EXTENSIONS; case LLFilePicker::FFLOAD_ALL: From adaaccd3d74dd05b596693ef7de90aeef20b5f9d Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Tue, 17 May 2022 15:54:00 -0600 Subject: [PATCH 06/17] SL-17214 additional glTF validation, remove dead code from DAE loader --- indra/llprimitive/CMakeLists.txt | 2 ++ indra/llprimitive/lldaeloader.cpp | 42 ---------------------------- indra/llprimitive/lldaeloader.h | 3 -- indra/llprimitive/llgltfloader.cpp | 44 +++++++++++++++++------------- indra/llprimitive/llgltfloader.h | 6 +++- 5 files changed, 32 insertions(+), 65 deletions(-) diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 9d75dab31e..2395841eae 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -10,12 +10,14 @@ include(LLCoreHttp) include(LLXML) include(LLPhysicsExtensions) include(LLCharacter) +include(LLRender) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada ${LIBS_PREBUILT_DIR}/include/collada/1.4 ${LLCHARACTER_INCLUDE_DIRS} diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 94f8500dab..68b29f01da 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -2504,20 +2504,6 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD& return (status == LLModel::NO_ERRORS); } -////static -//LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh) -//{ -// LLVolumeParams volume_params; -// volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); -// LLModel* ret = new LLModel(volume_params, 0.f); -// createVolumeFacesFromDomMesh(ret, mesh); -// if (ret->mLabel.empty()) -// { -// ret->mLabel = getElementLabel(mesh); -// } -// return ret; -//} - //static diff version supports creating multiple models when material counts spill // over the 8 face server-side limit // @@ -2608,31 +2594,3 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector& mo return true; } - -bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh) -{ - if (mesh) - { - pModel->ClearFacesAndMaterials(); - - LLSD placeholder; - addVolumeFacesFromDomMesh(pModel, mesh, placeholder); - - if (pModel->getNumVolumeFaces() > 0) - { - pModel->normalizeVolumeFaces(); - pModel->optimizeVolumeFaces(); - - if (pModel->getNumVolumeFaces() > 0) - { - return true; - } - } - } - else - { - LL_WARNS() << "no mesh found" << LL_ENDL; - } - - return false; -} diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h index 9e80980ddf..52ad908870 100644 --- a/indra/llprimitive/lldaeloader.h +++ b/indra/llprimitive/lldaeloader.h @@ -90,9 +90,6 @@ protected: bool verifyController( domController* pController ); static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh, LLSD& log_msg); - static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh); - - //static LLModel* loadModelFromDomMesh(domMesh* mesh); // Loads a mesh breaking it into one or more models as necessary // to get around volume face limitations while retaining >8 materials diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp index 001623ac9e..bc9c4760f7 100644 --- a/indra/llprimitive/llgltfloader.cpp +++ b/indra/llprimitive/llgltfloader.cpp @@ -211,9 +211,9 @@ bool LLGLTFLoader::parseMaterials() mSamplers.clear(); for (auto in_sampler : mGltfModel.samplers) { - gltf_sampler sampler{ 0 }; - sampler.magFilter = in_sampler.magFilter; - sampler.minFilter = in_sampler.minFilter; + gltf_sampler sampler; + sampler.magFilter = in_sampler.magFilter > 0 ? in_sampler.magFilter : GL_LINEAR; + sampler.minFilter = in_sampler.minFilter > 0 ? in_sampler.minFilter : GL_LINEAR;; sampler.wrapS = in_sampler.wrapS; sampler.wrapT = in_sampler.wrapT; sampler.name = in_sampler.name; // unused @@ -223,10 +223,10 @@ bool LLGLTFLoader::parseMaterials() mImages.clear(); for (auto in_image : mGltfModel.images) { - gltf_image image{ 0 }; + gltf_image image; image.numChannels = in_image.component; - image.bytesPerChannel = in_image.bits >> 3; - image.pixelType = in_image.pixel_type; + image.bytesPerChannel = in_image.bits >> 3; // Convert bits to bytes + image.pixelType = in_image.pixel_type; // Maps exactly, i.e. TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE == GL_UNSIGNED_BYTE, etc image.size = in_image.image.size(); image.height = in_image.height; image.width = in_image.width; @@ -250,7 +250,7 @@ bool LLGLTFLoader::parseMaterials() mTextures.clear(); for (auto in_tex : mGltfModel.textures) { - gltf_texture tex{ 0 }; + gltf_texture tex; tex.image_idx = in_tex.source; tex.sampler_idx = in_tex.sampler; @@ -266,18 +266,21 @@ bool LLGLTFLoader::parseMaterials() // parse each material for (tinygltf::Material gltf_material : mGltfModel.materials) { - gltf_render_material mat{ 0 }; + gltf_render_material mat; mat.name = gltf_material.name; mat.normalScale = gltf_material.normalTexture.scale; + mat.hasNormalTex = gltf_material.normalTexture.index > 0; mat.normalTexIdx = gltf_material.normalTexture.index; mat.normalTexCoordIdx = gltf_material.normalTexture.texCoord; mat.occlusionScale = gltf_material.occlusionTexture.strength; + mat.hasOcclusionTex = gltf_material.occlusionTexture.index > 0; mat.occlusionTexIdx = gltf_material.occlusionTexture.index; mat.occlusionTexCoordIdx = gltf_material.occlusionTexture.texCoord; mat.emissiveColor.set(gltf_material.emissiveFactor.data()); + mat.hasEmissiveTex = gltf_material.emissiveTexture.index > 0; mat.emissiveColorTexIdx = gltf_material.emissiveTexture.index; mat.emissiveColorTexCoordIdx = gltf_material.emissiveTexture.texCoord; @@ -288,29 +291,31 @@ bool LLGLTFLoader::parseMaterials() mat.hasPBR = true; mat.pbr.baseColor.set(pbr.baseColorFactor.data()); + mat.pbr.hasBaseTex = pbr.baseColorTexture.index > 0; mat.pbr.baseColorTexIdx = pbr.baseColorTexture.index; mat.pbr.baseColorTexCoordIdx = pbr.baseColorTexture.texCoord; mat.pbr.metalness = pbr.metallicFactor; mat.pbr.roughness = pbr.roughnessFactor; + mat.pbr.hasMRTex = pbr.metallicRoughnessTexture.index > 0; mat.pbr.metalRoughTexIdx = pbr.metallicRoughnessTexture.index; mat.pbr.metalRoughTexCoordIdx = pbr.metallicRoughnessTexture.texCoord; - if (mat.normalTexIdx >= mTextures.size() || - mat.occlusionTexIdx >= mTextures.size() || - mat.emissiveColorTexIdx >= mTextures.size() || - mat.pbr.baseColorTexIdx >= mTextures.size() || - mat.pbr.metalRoughTexIdx >= mTextures.size()) + if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) || + (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) || + (mat.hasEmissiveTex && (mat.emissiveColorTexIdx >= mTextures.size())) || + (mat.pbr.hasBaseTex && (mat.pbr.baseColorTexIdx >= mTextures.size())) || + (mat.pbr.hasMRTex && (mat.pbr.metalRoughTexIdx >= mTextures.size()))) { LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL; return false; } - if (mat.normalTexCoordIdx > 0 || // May have to loosen this condition - mat.occlusionTexCoordIdx > 0 || - mat.emissiveColorTexCoordIdx > 0 || - mat.pbr.baseColorTexCoordIdx > 0 || - mat.pbr.metalRoughTexCoordIdx > 0) + if ((mat.hasNormalTex && (mat.normalTexCoordIdx > 2)) || // mesh can have up to 3 sets of UV + (mat.hasOcclusionTex && (mat.occlusionTexCoordIdx > 2)) || + (mat.hasEmissiveTex && (mat.emissiveColorTexCoordIdx > 2)) || + (mat.pbr.hasBaseTex && (mat.pbr.baseColorTexCoordIdx > 2)) || + (mat.pbr.hasMRTex && (mat.pbr.metalRoughTexCoordIdx > 2))) { LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL; return false; @@ -331,6 +336,7 @@ void LLGLTFLoader::uploadMeshes() // TODO: convert raw index buffers to UUIDs void LLGLTFLoader::uploadMaterials() { - llassert(0); + //llassert(0); + } diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h index 9bffeef4ab..08e9836d07 100644 --- a/indra/llprimitive/llgltfloader.h +++ b/indra/llprimitive/llgltfloader.h @@ -27,8 +27,9 @@ #ifndef LL_LLGLTFLoader_H #define LL_LLGLTFLoader_H -#include "tinygltf\tiny_gltf.h" +#include "tinygltf/tiny_gltf.h" +#include "llglheaders.h" #include "llmodelloader.h" typedef struct // gltf sampler @@ -74,6 +75,8 @@ typedef struct // gltf_pbrMR_material U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel U32 metalRoughTexCoordIdx; + + bool hasBaseTex, hasMRTex; } gltf_pbr; typedef struct // render material @@ -100,6 +103,7 @@ typedef struct // render material // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry?? bool hasPBR; + bool hasNormalTex, hasOcclusionTex, hasEmissiveTex; gltf_pbr pbr; } gltf_render_material; From c9ebb970ee916ace16e88508dc1a178336a91d52 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Wed, 1 Jun 2022 14:37:20 -0600 Subject: [PATCH 07/17] SL-17214 re-work gltf data organization --- indra/llprimitive/llgltfloader.cpp | 138 +++++++++++++++++++++-------- indra/llprimitive/llgltfloader.h | 68 +++++++------- 2 files changed, 131 insertions(+), 75 deletions(-) diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp index bc9c4760f7..3ec11f70c6 100644 --- a/indra/llprimitive/llgltfloader.cpp +++ b/indra/llprimitive/llgltfloader.cpp @@ -45,6 +45,9 @@ // TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE #include "tinygltf\tiny_gltf.h" + +// TODO: includes inherited from dae loader. Validate / prune + #include #include "llsdserialize.h" @@ -120,9 +123,9 @@ bool LLGLTFLoader::OpenFile(const std::string &filename) if (!mGltfLoaded) { if (!warn_msg.empty()) - LL_WARNS() << "gltf load warning: " << warn_msg.c_str() << LL_ENDL; + LL_WARNS("GLTF_IMPORT") << "gltf load warning: " << warn_msg.c_str() << LL_ENDL; if (!error_msg.empty()) - LL_WARNS() << "gltf load error: " << error_msg.c_str() << LL_ENDL; + LL_WARNS("GLTF_IMPORT") << "gltf load error: " << error_msg.c_str() << LL_ENDL; return false; } @@ -251,10 +254,11 @@ bool LLGLTFLoader::parseMaterials() for (auto in_tex : mGltfModel.textures) { gltf_texture tex; - tex.image_idx = in_tex.source; - tex.sampler_idx = in_tex.sampler; + tex.imageIdx = in_tex.source; + tex.samplerIdx = in_tex.sampler; + tex.imageUuid.setNull(); - if (tex.image_idx >= mImages.size() || tex.sampler_idx >= mSamplers.size()) + if (tex.imageIdx >= mImages.size() || tex.samplerIdx >= mSamplers.size()) { LL_WARNS("GLTF_IMPORT") << "Texture sampler/image index error" << LL_ENDL; return false; @@ -269,53 +273,53 @@ bool LLGLTFLoader::parseMaterials() gltf_render_material mat; mat.name = gltf_material.name; + tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness; + mat.hasPBR = true; // Always true, for now + + mat.baseColor.set(pbr.baseColorFactor.data()); + mat.hasBaseTex = pbr.baseColorTexture.index >= 0; + mat.baseColorTexIdx = pbr.baseColorTexture.index; + mat.baseColorTexCoords = pbr.baseColorTexture.texCoord; + + mat.metalness = pbr.metallicFactor; + mat.roughness = pbr.roughnessFactor; + mat.hasMRTex = pbr.metallicRoughnessTexture.index >= 0; + mat.metalRoughTexIdx = pbr.metallicRoughnessTexture.index; + mat.metalRoughTexCoords = pbr.metallicRoughnessTexture.texCoord; + mat.normalScale = gltf_material.normalTexture.scale; - mat.hasNormalTex = gltf_material.normalTexture.index > 0; + mat.hasNormalTex = gltf_material.normalTexture.index >= 0; mat.normalTexIdx = gltf_material.normalTexture.index; - mat.normalTexCoordIdx = gltf_material.normalTexture.texCoord; + mat.normalTexCoords = gltf_material.normalTexture.texCoord; mat.occlusionScale = gltf_material.occlusionTexture.strength; - mat.hasOcclusionTex = gltf_material.occlusionTexture.index > 0; + mat.hasOcclusionTex = gltf_material.occlusionTexture.index >= 0; mat.occlusionTexIdx = gltf_material.occlusionTexture.index; - mat.occlusionTexCoordIdx = gltf_material.occlusionTexture.texCoord; + mat.occlusionTexCoords = gltf_material.occlusionTexture.texCoord; mat.emissiveColor.set(gltf_material.emissiveFactor.data()); - mat.hasEmissiveTex = gltf_material.emissiveTexture.index > 0; - mat.emissiveColorTexIdx = gltf_material.emissiveTexture.index; - mat.emissiveColorTexCoordIdx = gltf_material.emissiveTexture.texCoord; + mat.hasEmissiveTex = gltf_material.emissiveTexture.index >= 0; + mat.emissiveTexIdx = gltf_material.emissiveTexture.index; + mat.emissiveTexCoords = gltf_material.emissiveTexture.texCoord; mat.alphaMode = gltf_material.alphaMode; mat.alphaMask = gltf_material.alphaCutoff; - tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness; - mat.hasPBR = true; - - mat.pbr.baseColor.set(pbr.baseColorFactor.data()); - mat.pbr.hasBaseTex = pbr.baseColorTexture.index > 0; - mat.pbr.baseColorTexIdx = pbr.baseColorTexture.index; - mat.pbr.baseColorTexCoordIdx = pbr.baseColorTexture.texCoord; - - mat.pbr.metalness = pbr.metallicFactor; - mat.pbr.roughness = pbr.roughnessFactor; - mat.pbr.hasMRTex = pbr.metallicRoughnessTexture.index > 0; - mat.pbr.metalRoughTexIdx = pbr.metallicRoughnessTexture.index; - mat.pbr.metalRoughTexCoordIdx = pbr.metallicRoughnessTexture.texCoord; - - if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) || - (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) || - (mat.hasEmissiveTex && (mat.emissiveColorTexIdx >= mTextures.size())) || - (mat.pbr.hasBaseTex && (mat.pbr.baseColorTexIdx >= mTextures.size())) || - (mat.pbr.hasMRTex && (mat.pbr.metalRoughTexIdx >= mTextures.size()))) + if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) || + (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) || + (mat.hasEmissiveTex && (mat.emissiveTexIdx >= mTextures.size())) || + (mat.hasBaseTex && (mat.baseColorTexIdx >= mTextures.size())) || + (mat.hasMRTex && (mat.metalRoughTexIdx >= mTextures.size()))) { LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL; return false; } - if ((mat.hasNormalTex && (mat.normalTexCoordIdx > 2)) || // mesh can have up to 3 sets of UV - (mat.hasOcclusionTex && (mat.occlusionTexCoordIdx > 2)) || - (mat.hasEmissiveTex && (mat.emissiveColorTexCoordIdx > 2)) || - (mat.pbr.hasBaseTex && (mat.pbr.baseColorTexCoordIdx > 2)) || - (mat.pbr.hasMRTex && (mat.pbr.metalRoughTexCoordIdx > 2))) + if ((mat.hasNormalTex && (mat.normalTexCoords > 2)) || // mesh can have up to 3 sets of UV + (mat.hasOcclusionTex && (mat.occlusionTexCoords > 2)) || + (mat.hasEmissiveTex && (mat.emissiveTexCoords > 2)) || + (mat.hasBaseTex && (mat.baseColorTexCoords > 2)) || + (mat.hasMRTex && (mat.metalRoughTexCoords > 2))) { LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL; return false; @@ -333,10 +337,68 @@ void LLGLTFLoader::uploadMeshes() llassert(0); } -// TODO: convert raw index buffers to UUIDs +// convert raw image buffers to texture UUIDs & assemble into a render material void LLGLTFLoader::uploadMaterials() { - //llassert(0); + for (gltf_render_material mat : mMaterials) // Initially 1 material per gltf file, but design for multiple + { + if (mat.hasBaseTex) + { + gltf_texture& gtex = mTextures[mat.baseColorTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + if (mat.hasMRTex) + { + gltf_texture& gtex = mTextures[mat.metalRoughTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + + if (mat.hasNormalTex) + { + gltf_texture& gtex = mTextures[mat.normalTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + + if (mat.hasOcclusionTex) + { + gltf_texture& gtex = mTextures[mat.occlusionTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + + if (mat.hasEmissiveTex) + { + gltf_texture& gtex = mTextures[mat.emissiveTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + } } +LLUUID LLGLTFLoader::imageBufferToTextureUUID(const gltf_texture& tex) +{ + //gltf_image& image = mImages[tex.imageIdx]; + //gltf_sampler& sampler = mSamplers[tex.samplerIdx]; + + // fill an LLSD container with image+sampler data + + // upload texture + + // retrieve UUID + + return LLUUID::null; +} diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h index 08e9836d07..24496f6324 100644 --- a/indra/llprimitive/llgltfloader.h +++ b/indra/llprimitive/llgltfloader.h @@ -32,19 +32,21 @@ #include "llglheaders.h" #include "llmodelloader.h" +// gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD + typedef struct // gltf sampler { // Uses GL enums S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR S32 magFilter; // GL_NEAREST or GL_LINEAR S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT S32 wrapT; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT - //S32 wrapR; // seen in some sample files, but not part of glTF 2.0 spec. Ignored. + //S32 wrapR; // Found in some sample files, but not part of glTF 2.0 spec. Ignored. std::string name; // optional, currently unused // extensions and extras are sampler optional fields that we don't support - at least initially } gltf_sampler; typedef struct // gltf image -{ // Note that glTF images are defined with row 0 at the top +{ // Note that glTF images are defined with row 0 at the top (opposite of OpenGL) U8* data; // ptr to decoded image data U32 size; // in bytes, regardless of channel width U32 width; @@ -56,34 +58,19 @@ typedef struct // gltf image typedef struct // texture { - U32 image_idx; - U32 sampler_idx; + U32 imageIdx; + U32 samplerIdx; + LLUUID imageUuid = LLUUID::null; } gltf_texture; - -// TODO: 2022-05 DJH add UUIDs for each texture -typedef struct // gltf_pbrMR_material -{ - // scalar values - LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present. - double metalness; - double roughness; - - // textures - U32 baseColorTexIdx; // always sRGB encoded - U32 baseColorTexCoordIdx; - - U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel - U32 metalRoughTexCoordIdx; - - bool hasBaseTex, hasMRTex; -} gltf_pbr; - typedef struct // render material { std::string name; // scalar values + LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present. + double metalness; + double roughness; double normalScale; // scale applies only to X,Y components of normal double occlusionScale; // strength multiplier for occlusion LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent) @@ -91,20 +78,26 @@ typedef struct // render material double alphaMask; // textures - U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0) - U32 normalTexCoordIdx; + U32 baseColorTexIdx; // always sRGB encoded + U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel + U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0) + U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded + U32 emissiveTexIdx; // always stored as sRGB, in nits (candela / meter^2) - U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded - U32 occlusionTexCoordIdx; - - U32 emissiveColorTexIdx; // always stored as sRGB, in nits (candela / meter^2) - U32 emissiveColorTexCoordIdx; + // texture coordinates + U32 baseColorTexCoords; + U32 metalRoughTexCoords; + U32 normalTexCoords; + U32 occlusionTexCoords; + U32 emissiveTexCoords; // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry?? bool hasPBR; - bool hasNormalTex, hasOcclusionTex, hasEmissiveTex; - gltf_pbr pbr; + bool hasBaseTex, hasMRTex, hasNormalTex, hasOcclusionTex, hasEmissiveTex; + + // This field is populated after upload + LLUUID material_uuid = LLUUID::null; } gltf_render_material; @@ -112,7 +105,7 @@ typedef struct // gltf_mesh { std::string name; - // TODO DJH 2022-04 + // TODO add mesh import DJH 2022-04 } gltf_mesh; @@ -157,16 +150,17 @@ protected: std::vector mSamplers; private: - U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels -// bool mPreprocessGLTF; - bool parseMeshes(); void uploadMeshes(); bool parseMaterials(); void uploadMaterials(); bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh); + LLUUID imageBufferToTextureUUID(const gltf_texture& tex); - /* + U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels + // bool mPreprocessGLTF; + + /* Inherited from dae loader - unknown how useful here void processElement(gltfElement *element, bool &badElement, GLTF *gltf); void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin); From 2dc376aa5324448de7d15717d5e24b812d885eea Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Fri, 3 Jun 2022 10:15:56 -0600 Subject: [PATCH 08/17] SL-17214 add 3p-tinygltf dependency to autobuild.xml --- autobuild.xml | 60 ++++++++++++++++++++++++++++++++ indra/cmake/TinyGLTF.cmake | 7 ++++ indra/llprimitive/CMakeLists.txt | 2 ++ 3 files changed, 69 insertions(+) create mode 100644 indra/cmake/TinyGLTF.cmake diff --git a/autobuild.xml b/autobuild.xml index 4c69ff71d4..f80ed200a0 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3095,6 +3095,66 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors version 0.132.2 + tinygltf + + canonical_repo + https://bitbucket.org/lindenlab/3p-tinygltf + copyright + // Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many contributors. + description + tinygltf import library + license + MIT + license_file + LICENSES/tinygltf_license.txt + name + tinygltf + platforms + + darwin64 + + archive + + hash + 13ebc64d8ba6276105a3fd516c7224f0 + url + https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/100740/887434/tinygltf-v2.5.0-windows64-572388.tar.bz2 + + name + darwin64 + + windows + + archive + + hash + 13ebc64d8ba6276105a3fd516c7224f0 + url + https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/100740/887434/tinygltf-v2.5.0-windows64-572388.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 13ebc64d8ba6276105a3fd516c7224f0 + url + https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/100740/887434/tinygltf-v2.5.0-windows64-572388.tar.bz2 + + name + windows64 + + + source + https://bitbucket.org/lindenlab/3p-tinygltf + source_type + git + version + v2.5.0 + tracy canonical_repo diff --git a/indra/cmake/TinyGLTF.cmake b/indra/cmake/TinyGLTF.cmake new file mode 100644 index 0000000000..bb731637a0 --- /dev/null +++ b/indra/cmake/TinyGLTF.cmake @@ -0,0 +1,7 @@ +# -*- cmake -*- +include(Prebuilt) + +use_prebuilt_binary(tinygltf) + +set(TINYGLTF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinygltf) + diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 2395841eae..e131b12371 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -11,6 +11,7 @@ include(LLXML) include(LLPhysicsExtensions) include(LLCharacter) include(LLRender) +include(TinyGLTF) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -21,6 +22,7 @@ include_directories( ${LIBS_PREBUILT_DIR}/include/collada ${LIBS_PREBUILT_DIR}/include/collada/1.4 ${LLCHARACTER_INCLUDE_DIRS} + ${TINYGLTF_INCLUDE_DIR} ) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} From d3219f57c12ec29025e5c9c68b2cf90d49258672 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Tue, 7 Jun 2022 14:42:18 -0600 Subject: [PATCH 09/17] SL-17214 remove some dae clutter from gltf header --- indra/llprimitive/llgltfloader.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h index 24496f6324..9ee816e24e 100644 --- a/indra/llprimitive/llgltfloader.h +++ b/indra/llprimitive/llgltfloader.h @@ -75,7 +75,7 @@ typedef struct // render material double occlusionScale; // strength multiplier for occlusion LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent) std::string alphaMode; // "OPAQUE", "MASK" or "BLEND" - double alphaMask; + double alphaMask; // alpha cut-off // textures U32 baseColorTexIdx; // always sRGB encoded @@ -113,11 +113,6 @@ class LLGLTFLoader : public LLModelLoader { public: typedef std::map material_map; - typedef void gltfElement; // TBD - typedef void GLTF; // TBD - - // typedef std::map > > gltf_model_map; - // gltf_model_map mModelsMap; LLGLTFLoader(std::string filename, S32 lod, @@ -160,7 +155,8 @@ private: U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels // bool mPreprocessGLTF; - /* Inherited from dae loader - unknown how useful here + /* Below inherited from dae loader - unknown if/how useful here + void processElement(gltfElement *element, bool &badElement, GLTF *gltf); void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin); From 5f606069e29db5d9554ce6f4200d0d4c35ecc3a1 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 8 Jun 2022 17:48:58 -0500 Subject: [PATCH 10/17] SL-17285 Fix for probe influence volume combo box not applying. --- indra/newview/llpanelvolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index e7bbe266e5..f456ee4d4b 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -148,7 +148,7 @@ BOOL LLPanelVolume::postBuild() // REFLECTION PROBE Parameters { childSetCommitCallback("Reflection Probe Checkbox Ctrl", onCommitIsReflectionProbe, this); - childSetCommitCallback("Probe Shape Type Combo Ctrl", onCommitProbe, this); + childSetCommitCallback("Probe Volume Type Ctrl", onCommitProbe, this); childSetCommitCallback("Probe Ambiance", onCommitProbe, this); childSetCommitCallback("Probe Near Clip", onCommitProbe, this); From 125b099298652347991c521703109e12bccdd47e Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 9 Jun 2022 11:02:21 -0500 Subject: [PATCH 11/17] VS2019 build fix --- indra/llprimitive/llgltfloader.h | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h index 9ee816e24e..91389b5845 100644 --- a/indra/llprimitive/llgltfloader.h +++ b/indra/llprimitive/llgltfloader.h @@ -34,8 +34,10 @@ // gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD -typedef struct // gltf sampler -{ // Uses GL enums +class gltf_sampler +{ +public: + // Uses GL enums S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR S32 magFilter; // GL_NEAREST or GL_LINEAR S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT @@ -43,10 +45,11 @@ typedef struct // gltf sampler //S32 wrapR; // Found in some sample files, but not part of glTF 2.0 spec. Ignored. std::string name; // optional, currently unused // extensions and extras are sampler optional fields that we don't support - at least initially -} gltf_sampler; +}; -typedef struct // gltf image -{ // Note that glTF images are defined with row 0 at the top (opposite of OpenGL) +class gltf_image +{ +public:// Note that glTF images are defined with row 0 at the top (opposite of OpenGL) U8* data; // ptr to decoded image data U32 size; // in bytes, regardless of channel width U32 width; @@ -54,17 +57,19 @@ typedef struct // gltf image U32 numChannels; // range 1..4 U32 bytesPerChannel; // converted from gltf "bits", expects only 8, 16 or 32 as input U32 pixelType; // one of (TINYGLTF_COMPONENT_TYPE)_UNSIGNED_BYTE, _UNSIGNED_SHORT, _UNSIGNED_INT, or _FLOAT -} gltf_image; +}; -typedef struct // texture +class gltf_texture { +public: U32 imageIdx; U32 samplerIdx; LLUUID imageUuid = LLUUID::null; -} gltf_texture; +}; -typedef struct // render material +class gltf_render_material { +public: std::string name; // scalar values @@ -99,15 +104,16 @@ typedef struct // render material // This field is populated after upload LLUUID material_uuid = LLUUID::null; -} gltf_render_material; +}; -typedef struct // gltf_mesh +class gltf_mesh { +public: std::string name; // TODO add mesh import DJH 2022-04 -} gltf_mesh; +}; class LLGLTFLoader : public LLModelLoader { From 5b76111b2796372e7558dcda7493b6536c7962f9 Mon Sep 17 00:00:00 2001 From: Brad Kittenbrink Date: Thu, 9 Jun 2022 10:02:49 -0700 Subject: [PATCH 12/17] tinygltf updated with new public build for SL-17214 --- autobuild.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index f80ed200a0..1a9605b11d 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3140,9 +3140,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 13ebc64d8ba6276105a3fd516c7224f0 + 7fd9a99cea31809c89759905fbba30c9 url - https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/100740/887434/tinygltf-v2.5.0-windows64-572388.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2 name windows64 From d1dc9c35a94233f250a729becf9ccd4d88197198 Mon Sep 17 00:00:00 2001 From: Brad Kittenbrink Date: Thu, 9 Jun 2022 10:06:21 -0700 Subject: [PATCH 13/17] tinygltf also updated mac and 32bit windows packages with new public build for SL-17214 --- autobuild.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 1a9605b11d..aaff2d1360 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3116,9 +3116,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 13ebc64d8ba6276105a3fd516c7224f0 + 7fd9a99cea31809c89759905fbba30c9 url - https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/100740/887434/tinygltf-v2.5.0-windows64-572388.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2 name darwin64 @@ -3128,9 +3128,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 13ebc64d8ba6276105a3fd516c7224f0 + 7fd9a99cea31809c89759905fbba30c9 url - https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/100740/887434/tinygltf-v2.5.0-windows64-572388.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2 name windows From 0d9c23372bf8b34387b7d9de89234d3e9a5fd879 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 9 Jun 2022 14:09:33 -0500 Subject: [PATCH 14/17] SL-17551 Add "Select Reflection Probes" menu option and make invisible objects less annoying when alt-zooming in edit mode. --- indra/newview/app_settings/settings.xml | 11 +++++++ indra/newview/llcontrolavatar.cpp | 5 ++-- indra/newview/llcontrolavatar.h | 1 + indra/newview/llpanelvolume.cpp | 2 +- indra/newview/llreflectionmap.cpp | 2 +- indra/newview/llselectmgr.cpp | 8 +++-- indra/newview/llspatialpartition.cpp | 16 ++++++---- indra/newview/llspatialpartition.h | 2 ++ indra/newview/lltoolselect.cpp | 5 +++- indra/newview/llviewermenu.cpp | 13 +++++++++ indra/newview/llviewerobject.cpp | 13 +-------- indra/newview/llviewerobject.h | 6 ++-- indra/newview/llviewerobjectlist.cpp | 6 ++++ indra/newview/llviewerwindow.cpp | 29 +++++++++---------- indra/newview/llviewerwindow.h | 3 +- indra/newview/llvoavatar.cpp | 4 ++- indra/newview/llvoavatar.h | 2 ++ indra/newview/llvograss.cpp | 2 +- indra/newview/llvograss.h | 1 + indra/newview/llvopartgroup.cpp | 1 + indra/newview/llvopartgroup.h | 1 + indra/newview/llvosurfacepatch.cpp | 2 +- indra/newview/llvosurfacepatch.h | 1 + indra/newview/llvotree.cpp | 2 +- indra/newview/llvotree.h | 1 + indra/newview/llvovolume.cpp | 18 ++++++++---- indra/newview/llvovolume.h | 3 +- indra/newview/pipeline.cpp | 11 +++---- indra/newview/pipeline.h | 1 + .../skins/default/xui/en/menu_viewer.xml | 9 ++++++ 30 files changed, 120 insertions(+), 61 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f6c5d46c33..6df71e1019 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11191,6 +11191,17 @@ Value 0 + SelectReflectionProbes + + Comment + Select reflection probes + Persist + 1 + Type + Boolean + Value + 1 + SelectOwnedOnly Comment diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index 4a87273372..d4d4f641cf 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -610,6 +610,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV S32 face, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, @@ -627,7 +628,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV { LLVector4a local_end = end; LLVector4a local_intersection; - if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent)) + if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent)) { local_end = local_intersection; if (intersection) @@ -644,7 +645,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV for (std::vector::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it) { LLVOVolume *volp = *vol_it; - if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent)) + if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent)) { local_end = local_intersection; if (intersection) diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h index 8e87299f3e..ea91d70e69 100644 --- a/indra/newview/llcontrolavatar.h +++ b/indra/newview/llcontrolavatar.h @@ -68,6 +68,7 @@ public: S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index f456ee4d4b..fb2cf484f5 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -371,7 +371,7 @@ void LLPanelVolume::getState( ) } // Reflection Probe - BOOL is_probe = volobjp && volobjp->getIsReflectionProbe(); + BOOL is_probe = volobjp && volobjp->isReflectionProbe(); getChild("Reflection Probe Checkbox Ctrl")->setValue(is_probe); getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index f8a2020ccb..5991d7a170 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -139,7 +139,7 @@ void LLReflectionMap::autoAdjustOrigin() { int face = -1; LLVector4a intersection; - LLDrawable* drawable = mGroup->lineSegmentIntersect(bounds[0], corners[i], true, false, &face, &intersection); + LLDrawable* drawable = mGroup->lineSegmentIntersect(bounds[0], corners[i], true, false, true, &face, &intersection); if (drawable != nullptr) { hit = true; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 82a165cb35..7b4ba51859 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1066,8 +1066,9 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) return; } - if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) - || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced()))) + if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) + || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced())) + || (!gSavedSettings.getBOOL("SelectReflectionProbes") && !objectp->isReflectionProbe())) { // only select my own objects return; @@ -7127,7 +7128,8 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object, BOOL ignore_select_own if(!ignore_select_owned) { if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced()))) + (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced())) || + (!gSavedSettings.getBOOL("SelectReflectionProbes") && object->isReflectionProbe())) { // only select my own objects return FALSE; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 39bb46e6fa..a9e807e0f6 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3819,8 +3819,9 @@ public: LLDrawable* mHit; BOOL mPickTransparent; BOOL mPickRigged; + BOOL mPickUnselectable; - LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, + LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) : mStart(start), mEnd(end), @@ -3831,7 +3832,8 @@ public: mTangent(tangent), mHit(NULL), mPickTransparent(pick_transparent), - mPickRigged(pick_rigged) + mPickRigged(pick_rigged), + mPickUnselectable(pick_unselectable) { } @@ -3916,7 +3918,7 @@ public: LLVOAvatar* avatar = (LLVOAvatar*) vobj; if ((mPickRigged) || ((avatar->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) { - LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); + LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); if (hit) { mEnd = intersection; @@ -3932,7 +3934,7 @@ public: } } - if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent)) + if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent)) { mEnd = intersection; // shorten ray so we only find CLOSER hits if (mIntersection) @@ -3952,6 +3954,7 @@ public: LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, // return the face hit LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point @@ -3960,7 +3963,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co ) { - LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent); + LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, tex_coord, normal, tangent); LLDrawable* drawable = intersect.check(mOctree); return drawable; @@ -3969,6 +3972,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, // return the face hit LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point @@ -3977,7 +3981,7 @@ LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const ) { - LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent); + LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, tex_coord, normal, tangent); LLDrawable* drawable = intersect.check(getOctreeNode()); return drawable; diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index e9d84ecf06..bebd8aec85 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -317,6 +317,7 @@ public: LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, // return the face hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -400,6 +401,7 @@ public: LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, // return the face hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index e52bc0b015..790d9a8ec5 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -84,12 +84,14 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi } BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly"); BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); - + BOOL select_probe = gSavedSettings.getBOOL("SelectReflectionProbes"); + // *NOTE: These settings must be cleaned up at bottom of function. if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar) { gSavedSettings.setBOOL("SelectOwnedOnly", FALSE); gSavedSettings.setBOOL("SelectMovableOnly", FALSE); + gSavedSettings.setBOOL("SelectReflectionProbes", FALSE); LLSelectMgr::getInstance()->setForceSelection(TRUE); } @@ -241,6 +243,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi { gSavedSettings.setBOOL("SelectOwnedOnly", select_owned); gSavedSettings.setBOOL("SelectMovableOnly", select_movable); + gSavedSettings.setBOOL("SelectReflectionProbes", select_probe); LLSelectMgr::getInstance()->setForceSelection(FALSE); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9c8a666185..b99299528c 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7971,6 +7971,18 @@ class LLToolsSelectOnlyMovableObjects : public view_listener_t } }; +class LLToolsSelectReflectionProbes : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + BOOL cur_val = gSavedSettings.getBOOL("SelectReflectionProbes"); + + gSavedSettings.setBOOL("SelectReflectionProbes", !cur_val); + + return true; + } +}; + class LLToolsSelectBySurrounding : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -9200,6 +9212,7 @@ void initialize_menus() view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool"); view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects"); view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects"); + view_listener_t::addMenu(new LLToolsSelectReflectionProbes(), "Tools.SelectReflectionProbes"); view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding"); view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection"); view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius"); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 732beab448..d60fccdee3 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4573,6 +4573,7 @@ BOOL LLViewerObject::lineSegmentIntersect(const LLVector4a& start, const LLVecto S32 face, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, @@ -5509,18 +5510,6 @@ S32 LLViewerObject::countInventoryContents(LLAssetType::EType type) return count; } - -void LLViewerObject::setCanSelect(BOOL canSelect) -{ - mbCanSelect = canSelect; - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - child->mbCanSelect = canSelect; - } -} - void LLViewerObject::setDebugText(const std::string &utf8text) { if (utf8text.empty() && !mText) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 5b6d24887c..ddb0adaa23 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -239,6 +239,7 @@ public: virtual BOOL isMesh() const { return FALSE; } virtual BOOL isRiggedMesh() const { return FALSE; } virtual BOOL hasLightTexture() const { return FALSE; } + virtual BOOL isReflectionProbe() const { return FALSE; } // This method returns true if the object is over land owned by // the agent, one of its groups, or it encroaches and @@ -280,6 +281,7 @@ public: S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -421,8 +423,6 @@ public: void sendMaterialUpdate() const; - void setCanSelect(BOOL canSelect); - void setDebugText(const std::string &utf8text); void initHudText(); void restoreHudText(); @@ -678,7 +678,7 @@ public: // Selection, picking and rendering variables U32 mGLName; // GL "name" used by selection code - BOOL mbCanSelect; // true if user can select this object by clicking + BOOL mbCanSelect; // true if user can select this object by clicking under any circumstances (even if pick_unselectable is true) private: // Grabbed from UPDATE_FLAGS diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 0e585f13fc..593f593a0f 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1838,6 +1838,8 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er) void LLViewerObjectList::generatePickList(LLCamera &camera) { + llassert(false); +#if 0 //deprecated LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; LLViewerObject *objectp; @@ -1961,10 +1963,13 @@ void LLViewerObjectList::generatePickList(LLCamera &camera) LLHUDIcon::generatePickIDs(i * step, step); } +#endif } LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id) { + llassert(false); +#if 0 std::set::iterator pick_it; for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end(); ++pick_it) { @@ -1973,6 +1978,7 @@ LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id) return (*pick_it); } } +#endif return NULL; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 6a60671040..6613c8ac01 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3371,7 +3371,7 @@ void LLViewerWindow::updateUI() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) { gDebugRaycastFaceHit = -1; - gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, + gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, &gDebugRaycastFaceHit, &gDebugRaycastIntersection, &gDebugRaycastTexCoord, @@ -4195,13 +4195,11 @@ void LLViewerWindow::pickAsync( S32 x, BOOL pick_rigged, BOOL pick_unselectable) { - BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); - if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) - { - // build mode allows interaction with all transparent objects - // "Show Debug Alpha" means no object actually transparent - pick_transparent = TRUE; - } + // "Show Debug Alpha" means no object actually transparent + if (LLDrawPoolAlpha::sShowDebugAlpha) + { + pick_transparent = TRUE; + } LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, TRUE, pick_unselectable, callback); schedulePick(pick_info); @@ -4259,7 +4257,7 @@ void LLViewerWindow::returnEmptyPicks() } // Performs the GL object/land pick. -LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle) +LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle, BOOL pick_unselectable) { BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) @@ -4308,6 +4306,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de S32 this_face, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, LLVector4a *intersection, LLVector2 *uv, @@ -4378,7 +4377,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de { if (this_object->isHUDAttachment()) // is a HUD object? { - if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged, + if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, uv, normal, tangent)) { found = this_object; @@ -4386,7 +4385,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de } else // is a world object { - if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged, + if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, uv, normal, tangent)) { found = this_object; @@ -4400,7 +4399,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de if (!found) // if not found in HUD, look in world: { - found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, + found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, uv, normal, tangent); if (found && !pick_transparent) { @@ -5007,8 +5006,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear()); F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear()); - gObjectList.generatePickList(*LLViewerCamera::getInstance()); - // Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen. // In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y) @@ -6060,7 +6057,7 @@ void LLPickInfo::fetchResults() } LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, - NULL, -1, mPickTransparent, mPickRigged, &face_hit, + NULL, -1, mPickTransparent, mPickRigged, mPickUnselectable, &face_hit, &intersection, &uv, &normal, &tangent, &start, &end); mPickPt = mMousePt; @@ -6205,7 +6202,7 @@ void LLPickInfo::getSurfaceInfo() if (objectp) { if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f, - objectp, -1, mPickTransparent, mPickRigged, + objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable, &mObjectFace, &intersection, &mSTCoords, diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index c9cf7da8c7..38ec0e1ac8 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -405,7 +405,7 @@ public: BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, BOOL pick_unselectable = FALSE); - LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE); + LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE, BOOL pick_unselectable = TRUE); LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, LLVector4a* intersection); @@ -414,6 +414,7 @@ public: S32 this_face = -1, BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, LLVector4a *intersection = NULL, LLVector2 *uv = NULL, diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 314c22eb6c..4ec5c999ac 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1777,6 +1777,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& S32 face, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, @@ -1883,6 +1884,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector S32 face, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, @@ -1913,7 +1915,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector { LLViewerObject* attached_object = attachment_iter->get(); - if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent)) + if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent)) { local_end = local_intersection; if (intersection) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 3c3decaad6..a085d773dc 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -164,6 +164,7 @@ public: S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -174,6 +175,7 @@ public: S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 9a41eedb54..d109b7b34f 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -758,7 +758,7 @@ void LLVOGrass::updateDrawable(BOOL force_damped) } // virtual -BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, +BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index 5634e048eb..63876dc099 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -79,6 +79,7 @@ public: S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 04e9a4f179..cb4315a774 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -485,6 +485,7 @@ BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector S32 face, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 4e4d6e609d..a45d381dfa 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -74,6 +74,7 @@ public: S32 face, BOOL pick_transparent, BOOL pick_rigged, + BOOL pick_unselectable, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index b0af565867..6b56eaeb4a 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -880,7 +880,7 @@ void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride, } } -BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, +BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index 884dbb3be3..aed67162d1 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -85,6 +85,7 @@ public: S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 493162b47b..e26791aa29 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -1170,7 +1170,7 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) mDrawable->setPositionGroup(pos); } -BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, +BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index 93c22d2da3..996e970cf8 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -111,6 +111,7 @@ public: S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 6aef9ee7c0..8f5d2d1c29 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -986,7 +986,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) gPipeline.setLight(mDrawable, TRUE); } - if (getIsReflectionProbe()) + if (isReflectionProbe()) { updateReflectionProbePtr(); } @@ -3503,7 +3503,7 @@ F32 LLVOVolume::getLightCutoff() const void LLVOVolume::setIsReflectionProbe(BOOL is_probe) { - BOOL was_probe = getIsReflectionProbe(); + BOOL was_probe = isReflectionProbe(); if (is_probe != was_probe) { if (is_probe) @@ -3559,7 +3559,7 @@ void LLVOVolume::setReflectionProbeVolumeType(LLReflectionProbeParams::EInfluenc } -BOOL LLVOVolume::getIsReflectionProbe() const +BOOL LLVOVolume::isReflectionProbe() const { // HACK - make this object a Reflection Probe if a certain UUID is detected static LLCachedControl reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", ""); @@ -4507,7 +4507,7 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u void LLVOVolume::updateReflectionProbePtr() { - if (getIsReflectionProbe()) + if (isReflectionProbe()) { if (mReflectionProbe.isNull()) { @@ -4717,7 +4717,7 @@ LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const } -BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, +BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { @@ -4728,6 +4728,14 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& return FALSE; } + if (!pick_unselectable) + { + if (!LLSelectMgr::instance().canSelectObject(this)) + { + return FALSE; + } + } + BOOL ret = FALSE; LLVolume* volume = getVolume(); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 93a10781c2..ad7a2c5606 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -151,6 +151,7 @@ public: S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, BOOL pick_rigged = FALSE, + BOOL pick_unselectable = TRUE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -290,7 +291,7 @@ public: void setReflectionProbeNearClip(F32 near_clip); void setReflectionProbeVolumeType(LLReflectionProbeParams::EInfluenceVolumeType volume_type); - BOOL getIsReflectionProbe() const; + BOOL isReflectionProbe() const override; F32 getReflectionProbeAmbiance() const; F32 getReflectionProbeNearClip() const; LLReflectionProbeParams::EInfluenceVolumeType getReflectionProbeVolumeType() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3332185bfd..20a21a685c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6988,7 +6988,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE); if (part && hasRenderType(part->mDrawableType)) { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL); + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, TRUE, face_hit, &position, NULL, NULL, NULL); if (hit) { drawable = hit; @@ -7016,6 +7016,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, bool pick_transparent, bool pick_rigged, + bool pick_unselectable, S32* face_hit, LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point @@ -7049,7 +7050,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, LLSpatialPartition* part = region->getSpatialPartition(j); if (part && hasRenderType(part->mDrawableType)) { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent); + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, &position, tex_coord, normal, tangent); if (hit) { drawable = hit; @@ -7106,7 +7107,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_AVATAR); if (part && hasRenderType(part->mDrawableType)) { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent); + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, &position, tex_coord, normal, tangent); if (hit) { LLVector4a delta; @@ -7194,7 +7195,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, c LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD); if (part) { - LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, face_hit, intersection, tex_coord, normal, tangent); + LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, TRUE, face_hit, intersection, tex_coord, normal, tangent); if (hit) { drawable = hit; @@ -7695,7 +7696,7 @@ void LLPipeline::renderFinalize() LLVector4a result; result.clear(); - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result); + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); focus_point.set(result.getF32ptr()); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index bb2e1d65ae..f4c55bde7d 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -188,6 +188,7 @@ public: LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, bool pick_transparent, bool pick_rigged, + bool pick_unselectable, S32* face_hit, // return the face hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 0b0f8e17bc..159b9aebd0 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1417,6 +1417,15 @@ function="World.EnvPreset" function="Tools.SelectOnlyMovableObjects" parameter="movable" /> + + + + From bc85cc300d32c543ab80204a9b2fcf54b4b11935 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 9 Jun 2022 14:26:23 -0500 Subject: [PATCH 15/17] SL-17551 Followup -- remove some dead pick-render related code. --- indra/newview/lldrawable.cpp | 3 - indra/newview/llhudicon.cpp | 52 +------- indra/newview/llhudicon.h | 5 - indra/newview/llviewerobject.cpp | 1 - indra/newview/llviewerobject.h | 6 +- indra/newview/llviewerobjectlist.cpp | 173 +-------------------------- indra/newview/llviewerobjectlist.h | 8 -- 7 files changed, 6 insertions(+), 242 deletions(-) diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 4a0c9d399f..bfb79f3a4c 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -249,12 +249,9 @@ void LLDrawable::cleanupReferences() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; - std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); mFaces.clear(); - gObjectList.removeDrawable(this); - gPipeline.unlinkDrawable(this); removeFromOctree(); diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp index 85a878c4a2..60294f6a51 100644 --- a/indra/newview/llhudicon.cpp +++ b/indra/newview/llhudicon.cpp @@ -64,7 +64,6 @@ LLHUDIcon::icon_instance_t LLHUDIcon::sIconInstances; LLHUDIcon::LLHUDIcon(const U8 type) : LLHUDObject(type), mImagep(NULL), - mPickID(0), mScale(0.1f), mHidden(FALSE) { @@ -76,15 +75,11 @@ LLHUDIcon::~LLHUDIcon() mImagep = NULL; } -void LLHUDIcon::renderIcon(BOOL for_select) +void LLHUDIcon::render() { LLGLSUIDefault texture_state; LLGLDepthTest gls_depth(GL_TRUE); LLGLDisable gls_stencil(GL_STENCIL_TEST); - if (for_select) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } if (mHidden) return; @@ -116,7 +111,7 @@ void LLHUDIcon::renderIcon(BOOL for_select) mDistance = dist_vec(icon_position, camera->getOrigin()); - F32 alpha_factor = for_select ? 1.f : clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f); + F32 alpha_factor = clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f); LLVector3 x_pixel_vec; LLVector3 y_pixel_vec; @@ -150,13 +145,6 @@ void LLHUDIcon::renderIcon(BOOL for_select) LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale; LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale; - if (for_select) - { - // set color to unique color id for picking - LLColor4U coloru((U8)(mPickID >> 16), (U8)(mPickID >> 8), (U8)mPickID); - gGL.color4ubv(coloru.mV); - } - else { LLColor4 icon_color = LLColor4::white; icon_color.mV[VALPHA] = alpha_factor; @@ -198,11 +186,6 @@ void LLHUDIcon::markDead() LLHUDObject::markDead(); } -void LLHUDIcon::render() -{ - renderIcon(FALSE); -} - BOOL LLHUDIcon::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection) { if (mHidden) @@ -295,37 +278,6 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& return FALSE; } -//static -S32 LLHUDIcon::generatePickIDs(S32 start_id, S32 step_size) -{ - S32 cur_id = start_id; - icon_instance_t::iterator icon_it; - - for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it) - { - (*icon_it)->mPickID = cur_id; - cur_id += step_size; - } - - return cur_id; -} - -//static -LLHUDIcon* LLHUDIcon::handlePick(S32 pick_id) -{ - icon_instance_t::iterator icon_it; - - for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it) - { - if (pick_id == (*icon_it)->mPickID) - { - return *icon_it; - } - } - - return NULL; -} - //static LLHUDIcon* LLHUDIcon::lineSegmentIntersectAll(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection) { diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h index e00a985ddc..7f452b5c36 100644 --- a/indra/newview/llhudicon.h +++ b/indra/newview/llhudicon.h @@ -56,8 +56,6 @@ public: void restartLifeTimer() { mLifeTimer.reset(); } - static S32 generatePickIDs(S32 start_id, S32 step_size); - static LLHUDIcon* handlePick(S32 pick_id); static LLHUDIcon* lineSegmentIntersectAll(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection); static void updateAll(); @@ -75,14 +73,11 @@ protected: LLHUDIcon(const U8 type); ~LLHUDIcon(); - void renderIcon(BOOL for_select); // common render code - private: LLPointer mImagep; LLFrameTimer mAnimTimer; LLFrameTimer mLifeTimer; F32 mDistance; - S32 mPickID; F32 mScale; BOOL mHidden; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index d60fccdee3..857a94d7be 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -259,7 +259,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mTEImages(NULL), mTENormalMaps(NULL), mTESpecularMaps(NULL), - mGLName(0), mbCanSelect(TRUE), mFlags(0), mPhysicsShapeType(0), diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index ddb0adaa23..1c4cfc6466 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -676,9 +676,9 @@ public: LLPointer *mTENormalMaps; LLPointer *mTESpecularMaps; - // Selection, picking and rendering variables - U32 mGLName; // GL "name" used by selection code - BOOL mbCanSelect; // true if user can select this object by clicking under any circumstances (even if pick_unselectable is true) + // true if user can select this object by clicking under any circumstances (even if pick_unselectable is true) + // can likely be factored out + BOOL mbCanSelect; private: // Grabbed from UPDATE_FLAGS diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 593f593a0f..47a996d894 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1339,38 +1339,13 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) } // Don't clean up mObject references, these will be cleaned up more efficiently later! - // Also, not cleaned up - removeDrawable(objectp->mDrawable); - + if(new_dead_object) { mNumDeadObjects++; } } -void LLViewerObjectList::removeDrawable(LLDrawable* drawablep) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; - - if (!drawablep) - { - return; - } - - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace* facep = drawablep->getFace(i) ; - if(facep) - { - LLViewerObject* objectp = facep->getViewerObject(); - if(objectp) - { - mSelectPickList.erase(objectp); - } - } - } -} - BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) { // Don't ever kill gAgentAvatarp, just force it to the agent's region @@ -1836,152 +1811,6 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er) { } -void LLViewerObjectList::generatePickList(LLCamera &camera) -{ - llassert(false); -#if 0 //deprecated - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - - LLViewerObject *objectp; - S32 i; - // Reset all of the GL names to zero. - for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) - { - (*iter)->mGLName = 0; - } - - mSelectPickList.clear(); - - std::vector pick_drawables; - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - part->cull(camera, &pick_drawables, TRUE); - } - } - } - - for (std::vector::iterator iter = pick_drawables.begin(); - iter != pick_drawables.end(); iter++) - { - LLDrawable* drawablep = *iter; - if( !drawablep ) - continue; - - LLViewerObject* last_objectp = NULL; - for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++) - { - LLFace * facep = drawablep->getFace(face_num); - if (!facep) continue; - - LLViewerObject* objectp = facep->getViewerObject(); - - if (objectp && objectp != last_objectp) - { - mSelectPickList.insert(objectp); - last_objectp = objectp; - } - } - } - - LLHUDNameTag::addPickable(mSelectPickList); - - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - objectp = (LLVOAvatar*) *iter; - if (!objectp->isDead()) - { - if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible()) - { - mSelectPickList.insert(objectp); - } - } - } - - // add all hud objects to pick list - if (isAgentAvatarValid()) - { - for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); - iter != gAgentAvatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - if (attachment->getIsHUDAttachment()) - { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - if (LLViewerObject* attached_object = attachment_iter->get()) - { - mSelectPickList.insert(attached_object); - LLViewerObject::const_child_list_t& child_list = attached_object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* childp = *iter; - if (childp) - { - mSelectPickList.insert(childp); - } - } - } - } - } - } - } - - S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances(); - - if (num_pickables != 0) - { - S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables; - - std::set::iterator pick_it; - i = 0; - for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();) - { - LLViewerObject* objp = (*pick_it); - if (!objp || objp->isDead() || !objp->mbCanSelect) - { - mSelectPickList.erase(pick_it++); - continue; - } - - objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET; - i++; - ++pick_it; - } - - LLHUDIcon::generatePickIDs(i * step, step); - } -#endif -} - -LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id) -{ - llassert(false); -#if 0 - std::set::iterator pick_it; - for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end(); ++pick_it) - { - if ((*pick_it)->mGLName == object_id) - { - return (*pick_it); - } - } -#endif - return NULL; -} - void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent, const std::string &string, const LLColor4 &color, diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 72b2b99004..f2cba8c259 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -77,7 +77,6 @@ public: BOOL killObject(LLViewerObject *objectp); void killObjects(LLViewerRegion *regionp); // Kill all objects owned by a particular region. void killAllObjects(); - void removeDrawable(LLDrawable* drawablep); void cleanDeadObjects(const BOOL use_timer = TRUE); // Clean up the dead object list. @@ -129,11 +128,6 @@ public: void updateAvatarVisibility(); - // Selection related stuff - void generatePickList(LLCamera &camera); - - LLViewerObject *getSelectedObject(const U32 object_id); - inline S32 getNumObjects() { return (S32) mObjects.size(); } inline S32 getNumActiveObjects() { return (S32) mActiveObjects.size(); } @@ -226,8 +220,6 @@ protected: static std::map sIndexAndLocalIDToUUID; - std::set mSelectPickList; - friend class LLViewerObject; private: From 03d85bfb33f53e658256d8bedcf0b4262226cf90 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 9 Jun 2022 19:43:21 -0500 Subject: [PATCH 16/17] SL-17573 Add "dynamic" checkbox, also followup on SL-17551 and do "Select Invisible Objects" checkbox instead of "Select Reflection Probes" --- indra/llprimitive/llprimitive.cpp | 103 +++++++++++------- indra/llprimitive/llprimitive.h | 15 +-- indra/newview/app_settings/settings.xml | 4 +- indra/newview/llpanelvolume.cpp | 37 +++---- indra/newview/llreflectionmap.cpp | 14 ++- indra/newview/llreflectionmap.h | 3 + indra/newview/llselectmgr.cpp | 6 +- indra/newview/lltoolselect.cpp | 10 +- indra/newview/llviewermenu.cpp | 8 +- indra/newview/llviewerwindow.cpp | 46 ++++++-- indra/newview/llviewerwindow.h | 2 +- indra/newview/llvovolume.cpp | 36 ++++-- indra/newview/llvovolume.h | 6 +- indra/newview/pipeline.cpp | 9 -- .../skins/default/xui/en/floater_tools.xml | 17 ++- .../skins/default/xui/en/menu_viewer.xml | 10 +- 16 files changed, 205 insertions(+), 121 deletions(-) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 6044048d09..9e0a079fd9 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1819,92 +1819,117 @@ bool LLLightParams::fromLLSD(LLSD& sd) //============================================================================ +//============================================================================ + LLReflectionProbeParams::LLReflectionProbeParams() { mType = PARAMS_REFLECTION_PROBE; } -BOOL LLReflectionProbeParams::pack(LLDataPacker& dp) const +BOOL LLReflectionProbeParams::pack(LLDataPacker &dp) const { - dp.packF32(mAmbiance, "ambiance"); + dp.packF32(mAmbiance, "ambiance"); dp.packF32(mClipDistance, "clip_distance"); - dp.packU8(mVolumeType, "volume_type"); - return TRUE; + dp.packU8(mFlags, "flags"); + return TRUE; } -BOOL LLReflectionProbeParams::unpack(LLDataPacker& dp) +BOOL LLReflectionProbeParams::unpack(LLDataPacker &dp) { - F32 ambiance; + F32 ambiance; F32 clip_distance; - U8 volume_type; - - dp.unpackF32(ambiance, "ambiance"); - setAmbiance(ambiance); + dp.unpackF32(ambiance, "ambiance"); + setAmbiance(ambiance); + dp.unpackF32(clip_distance, "clip_distance"); - setClipDistance(clip_distance); - - dp.unpackU8(volume_type, "volume_type"); - setVolumeType((EInfluenceVolumeType)volume_type); - - return TRUE; + setClipDistance(clip_distance); + + dp.unpackU8(mFlags, "flags"); + + return TRUE; } bool LLReflectionProbeParams::operator==(const LLNetworkData& data) const { - if (data.mType != PARAMS_REFLECTION_PROBE) - { - return false; - } - const LLReflectionProbeParams* param = (const LLReflectionProbeParams*)&data; - if (param->mAmbiance != mAmbiance) - { - return false; - } + if (data.mType != PARAMS_REFLECTION_PROBE) + { + return false; + } + const LLReflectionProbeParams *param = (const LLReflectionProbeParams*)&data; + if (param->mAmbiance != mAmbiance) + { + return false; + } if (param->mClipDistance != mClipDistance) { return false; } - if (param->mVolumeType != mVolumeType) + if (param->mFlags != mFlags) { return false; } - return true; + return true; } void LLReflectionProbeParams::copy(const LLNetworkData& data) { - const LLReflectionProbeParams* param = (LLReflectionProbeParams*)&data; - mType = param->mType; - mAmbiance = param->mAmbiance; + const LLReflectionProbeParams *param = (LLReflectionProbeParams*)&data; + mType = param->mType; + mAmbiance = param->mAmbiance; mClipDistance = param->mClipDistance; - mVolumeType = param->mVolumeType; + mFlags = param->mFlags; } LLSD LLReflectionProbeParams::asLLSD() const { - LLSD sd; - sd["ambiance"] = getAmbiance(); + LLSD sd; + sd["ambiance"] = getAmbiance(); sd["clip_distance"] = getClipDistance(); - sd["volume_type"] = (U8) getVolumeType(); - return sd; + sd["flags"] = mFlags; + return sd; } bool LLReflectionProbeParams::fromLLSD(LLSD& sd) { if (!sd.has("ambiance") || !sd.has("clip_distance") || - !sd.has("volume_type")) + !sd.has("flags")) { return false; } - setAmbiance((F32)sd["ambiance"].asReal()); + setAmbiance((F32)sd["ambiance"].asReal()); setClipDistance((F32)sd["clip_distance"].asReal()); - setVolumeType((EInfluenceVolumeType)sd["volume_type"].asInteger()); - + mFlags = (U8) sd["flags"].asInteger(); + return true; } + +void LLReflectionProbeParams::setIsBox(bool is_box) +{ + if (is_box) + { + mFlags |= FLAG_BOX_VOLUME; + } + else + { + mFlags &= ~FLAG_BOX_VOLUME; + } +} + +void LLReflectionProbeParams::setIsDynamic(bool is_dynamic) +{ + if (is_dynamic) + { + mFlags |= FLAG_DYNAMIC; + } + else + { + mFlags &= ~FLAG_DYNAMIC; + } +} + //============================================================================ LLFlexibleObjectData::LLFlexibleObjectData() { diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 2215133e16..25196fb894 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -182,17 +182,16 @@ extern const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE; class LLReflectionProbeParams : public LLNetworkData { public: - enum EInfluenceVolumeType : U8 + enum EFlags : U8 { - VOLUME_TYPE_SPHERE = 0, // use a sphere influence volume - VOLUME_TYPE_BOX = 1, // use a box influence volume - DEFAULT_VOLUME_TYPE = VOLUME_TYPE_SPHERE + FLAG_BOX_VOLUME = 0x01, // use a box influence volume + FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe }; protected: F32 mAmbiance = REFLECTION_PROBE_DEFAULT_AMBIANCE; F32 mClipDistance = REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE; - EInfluenceVolumeType mVolumeType = DEFAULT_VOLUME_TYPE; + U8 mFlags = 0; public: LLReflectionProbeParams(); @@ -208,11 +207,13 @@ public: void setAmbiance(F32 ambiance) { mAmbiance = llclamp(ambiance, REFLECTION_PROBE_MIN_AMBIANCE, REFLECTION_PROBE_MAX_AMBIANCE); } void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); } - void setVolumeType(EInfluenceVolumeType type) { mVolumeType = llclamp(type, VOLUME_TYPE_SPHERE, VOLUME_TYPE_BOX); } + void setIsBox(bool is_box); + void setIsDynamic(bool is_dynamic); F32 getAmbiance() const { return mAmbiance; } F32 getClipDistance() const { return mClipDistance; } - EInfluenceVolumeType getVolumeType() const { return mVolumeType; } + bool getIsBox() const { return (mFlags & FLAG_BOX_VOLUME) != 0; } + bool getIsDynamic() const { return (mFlags & FLAG_DYNAMIC) != 0; } }; //------------------------------------------------- diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6df71e1019..327dfe6955 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11191,10 +11191,10 @@ Value 0 - SelectReflectionProbes + SelectInvisibleObjects Comment - Select reflection probes + Select invisible objects Persist 1 Type diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index fb2cf484f5..ddce22fa20 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -147,8 +147,9 @@ BOOL LLPanelVolume::postBuild() // REFLECTION PROBE Parameters { - childSetCommitCallback("Reflection Probe Checkbox Ctrl", onCommitIsReflectionProbe, this); - childSetCommitCallback("Probe Volume Type Ctrl", onCommitProbe, this); + childSetCommitCallback("Reflection Probe", onCommitIsReflectionProbe, this); + childSetCommitCallback("Probe Dynamic", onCommitProbe, this); + childSetCommitCallback("Probe Volume Type", onCommitProbe, this); childSetCommitCallback("Probe Ambiance", onCommitProbe, this); childSetCommitCallback("Probe Near Clip", onCommitProbe, this); @@ -372,25 +373,27 @@ void LLPanelVolume::getState( ) // Reflection Probe BOOL is_probe = volobjp && volobjp->isReflectionProbe(); - getChild("Reflection Probe Checkbox Ctrl")->setValue(is_probe); - getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); + getChild("Reflection Probe")->setValue(is_probe); + getChildView("Reflection Probe")->setEnabled(editable && single_volume && volobjp); bool probe_enabled = is_probe && editable && single_volume; - getChildView("Probe Volume Type Ctrl")->setEnabled(probe_enabled); + getChildView("Probe Dynamic")->setEnabled(probe_enabled); + getChildView("Probe Volume Type")->setEnabled(probe_enabled); getChildView("Probe Ambiance")->setEnabled(probe_enabled); getChildView("Probe Near Clip")->setEnabled(probe_enabled); if (!probe_enabled) { - getChild("Probe Volume Type Ctrl", true)->clear(); + getChild("Probe Volume Type", true)->clear(); getChild("Probe Ambiance", true)->clear(); getChild("Probe Near Clip", true)->clear(); + getChild("Probe Dynamic", true)->clear(); } else { std::string volume_type; - if (volobjp->getReflectionProbeVolumeType() == LLReflectionProbeParams::VOLUME_TYPE_BOX) + if (volobjp->getReflectionProbeIsBox()) { volume_type = "Box"; } @@ -399,9 +402,10 @@ void LLPanelVolume::getState( ) volume_type = "Sphere"; } - getChild("Probe Volume Type Ctrl", true)->setValue(volume_type); + getChild("Probe Volume Type", true)->setValue(volume_type); getChild("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance()); getChild("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip()); + getChild("Probe Dynamic", true)->setValue(volobjp->getReflectionProbeIsDynamic()); } // Animated Mesh @@ -692,7 +696,8 @@ void LLPanelVolume::clearCtrls() getChildView("Light Falloff")->setEnabled(false); getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(false);; - getChildView("Probe Volume Type Ctrl")->setEnabled(false); + getChildView("Probe Volume Type")->setEnabled(false); + getChildView("Probe Dynamic")->setEnabled(false); getChildView("Probe Ambiance")->setEnabled(false); getChildView("Probe Near Clip")->setEnabled(false); getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false); @@ -1003,19 +1008,11 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) volobjp->setReflectionProbeAmbiance((F32)self->getChild("Probe Ambiance")->getValue().asReal()); volobjp->setReflectionProbeNearClip((F32)self->getChild("Probe Near Clip")->getValue().asReal()); + volobjp->setReflectionProbeIsDynamic(self->getChild("Probe Dynamic")->getValue().asBoolean()); - std::string shape_type = self->getChild("Probe Volume Type Ctrl")->getValue().asString(); - LLReflectionProbeParams::EInfluenceVolumeType volume_type = LLReflectionProbeParams::DEFAULT_VOLUME_TYPE; + std::string shape_type = self->getChild("Probe Volume Type")->getValue().asString(); - if (shape_type == "Sphere") - { - volume_type = LLReflectionProbeParams::VOLUME_TYPE_SPHERE; - } - else if (shape_type == "Box") - { - volume_type = LLReflectionProbeParams::VOLUME_TYPE_BOX; - } - volobjp->setReflectionProbeVolumeType(volume_type); + volobjp->setReflectionProbeIsBox(shape_type == "Box"); } // static diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 5991d7a170..39e0841fc5 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -51,7 +51,7 @@ void LLReflectionMap::update(U32 resolution, U32 face) { resolution /= 2; } - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip()); + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic()); } bool LLReflectionMap::shouldUpdate() @@ -243,6 +243,16 @@ F32 LLReflectionMap::getNearClip() return llmax(ret, MINIMUM_NEAR_CLIP); } +bool LLReflectionMap::getIsDynamic() +{ + if (mViewerObject && mViewerObject->getVolume()) + { + return ((LLVOVolume*)mViewerObject)->getReflectionProbeIsDynamic(); + } + + return false; +} + bool LLReflectionMap::getBox(LLMatrix4& box) { if (mViewerObject) @@ -252,7 +262,7 @@ bool LLReflectionMap::getBox(LLMatrix4& box) { LLVOVolume* vobjp = (LLVOVolume*)mViewerObject; - if (vobjp->getReflectionProbeVolumeType() == LLReflectionProbeParams::VOLUME_TYPE_BOX) + if (vobjp->getReflectionProbeIsBox()) { glh::matrix4f mv(gGLModelView); glh::matrix4f scale; diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index a358bf5fdf..071568e53c 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -61,6 +61,9 @@ public: // Get the near clip plane distance to use for this probe F32 getNearClip(); + // Return true if this probe should include avatars in its reflection map + bool getIsDynamic(); + // get the encoded bounding box of this probe's influence volume // will only return a box if this probe is associated with a VOVolume // with its reflection probe influence volume to to VOLUME_TYPE_BOX diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 7b4ba51859..853703b4d5 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1067,8 +1067,7 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) } if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) - || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced())) - || (!gSavedSettings.getBOOL("SelectReflectionProbes") && !objectp->isReflectionProbe())) + || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced()))) { // only select my own objects return; @@ -7128,8 +7127,7 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object, BOOL ignore_select_own if(!ignore_select_owned) { if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced())) || - (!gSavedSettings.getBOOL("SelectReflectionProbes") && object->isReflectionProbe())) + (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced()))) { // only select my own objects return FALSE; diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 790d9a8ec5..c6f3905ddc 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -65,7 +65,8 @@ BOOL LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask) { // do immediate pick query BOOL pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick"); - mPick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged); + BOOL pick_transparent = gSavedSettings.getBOOL("SelectInvisibleObjects"); + mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged); // Pass mousedown to agent LLTool::handleMouseDown(x, y, mask); @@ -84,15 +85,13 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi } BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly"); BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); - BOOL select_probe = gSavedSettings.getBOOL("SelectReflectionProbes"); - // *NOTE: These settings must be cleaned up at bottom of function. + // *NOTE: These settings must be cleaned up at bottom of function. if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar) { gSavedSettings.setBOOL("SelectOwnedOnly", FALSE); gSavedSettings.setBOOL("SelectMovableOnly", FALSE); - gSavedSettings.setBOOL("SelectReflectionProbes", FALSE); - LLSelectMgr::getInstance()->setForceSelection(TRUE); + LLSelectMgr::getInstance()->setForceSelection(TRUE); } BOOL extend_select = (pick.mKeyMask == MASK_SHIFT) || (pick.mKeyMask == MASK_CONTROL); @@ -243,7 +242,6 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi { gSavedSettings.setBOOL("SelectOwnedOnly", select_owned); gSavedSettings.setBOOL("SelectMovableOnly", select_movable); - gSavedSettings.setBOOL("SelectReflectionProbes", select_probe); LLSelectMgr::getInstance()->setForceSelection(FALSE); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index b99299528c..b7f94a7e0c 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7971,13 +7971,13 @@ class LLToolsSelectOnlyMovableObjects : public view_listener_t } }; -class LLToolsSelectReflectionProbes : public view_listener_t +class LLToolsSelectInvisibleObjects : public view_listener_t { bool handleEvent(const LLSD& userdata) { - BOOL cur_val = gSavedSettings.getBOOL("SelectReflectionProbes"); + BOOL cur_val = gSavedSettings.getBOOL("SelectInvisibleObjects"); - gSavedSettings.setBOOL("SelectReflectionProbes", !cur_val); + gSavedSettings.setBOOL("SelectInvisibleObjects", !cur_val); return true; } @@ -9212,7 +9212,7 @@ void initialize_menus() view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool"); view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects"); view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects"); - view_listener_t::addMenu(new LLToolsSelectReflectionProbes(), "Tools.SelectReflectionProbes"); + view_listener_t::addMenu(new LLToolsSelectInvisibleObjects(), "Tools.SelectInvisibleObjects"); view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding"); view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection"); view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 6613c8ac01..1230a6d327 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4196,10 +4196,15 @@ void LLViewerWindow::pickAsync( S32 x, BOOL pick_unselectable) { // "Show Debug Alpha" means no object actually transparent + BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); if (LLDrawPoolAlpha::sShowDebugAlpha) { pick_transparent = TRUE; } + else if (in_build_mode && !gSavedSettings.getBOOL("SelectInvisibleObjects")) + { + pick_transparent = FALSE; + } LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, TRUE, pick_unselectable, callback); schedulePick(pick_info); @@ -4260,7 +4265,7 @@ void LLViewerWindow::returnEmptyPicks() LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle, BOOL pick_unselectable) { BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); - if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) + if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || LLDrawPoolAlpha::sShowDebugAlpha) { // build mode allows interaction with all transparent objects // "Show Debug Alpha" means no object actually transparent @@ -5267,7 +5272,7 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ void display_cube_face(); -BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip) +BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render) { // NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; @@ -5300,16 +5305,33 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + U32 dynamic_render_types[] = { + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_CONTROL_AV, + LLPipeline::RENDER_TYPE_PARTICLES + }; + constexpr U32 dynamic_render_type_count = sizeof(dynamic_render_types) / sizeof(U32); + bool prev_dynamic_render_type[dynamic_render_type_count]; + + + if (!dynamic_render) + { + for (int i = 0; i < dynamic_render_type_count; ++i) + { + prev_dynamic_render_type[i] = gPipeline.hasRenderType(dynamic_render_types[i]); + if (prev_dynamic_render_type[i]) + { + gPipeline.toggleRenderType(dynamic_render_types[i]); + } + } + } + BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE; if (prev_draw_ui != false) { LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); } - BOOL prev_draw_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - if (prev_draw_particles) - { - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - } + LLPipeline::sShowHUDAttachments = FALSE; LLRect window_rect = getWorldViewRectRaw(); @@ -5365,9 +5387,15 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea } } - if (prev_draw_particles) + if (!dynamic_render) { - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + for (int i = 0; i < dynamic_render_type_count; ++i) + { + if (prev_dynamic_render_type[i]) + { + gPipeline.toggleRenderType(dynamic_render_types[i]); + } + } } LLPipeline::sShowHUDAttachments = TRUE; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 38ec0e1ac8..387a2cb06f 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -370,7 +370,7 @@ public: // index - cube index in the array to use (cube index, not face-layer) // face - which cube face to update // near_clip - near clip setting to use - BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip); + BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars); // special implementation of simpleSnapshot for reflection maps diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8f5d2d1c29..3a619b4fcc 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3545,14 +3545,27 @@ void LLVOVolume::setReflectionProbeNearClip(F32 near_clip) } } -void LLVOVolume::setReflectionProbeVolumeType(LLReflectionProbeParams::EInfluenceVolumeType volume_type) +void LLVOVolume::setReflectionProbeIsBox(bool is_box) { LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); if (param_block) { - if (param_block->getVolumeType() != volume_type) + if (param_block->getIsBox() != is_box) { - param_block->setVolumeType(volume_type); + param_block->setIsBox(is_box); + parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); + } + } +} + +void LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic) +{ + LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + if (param_block->getIsDynamic() != is_dynamic) + { + param_block->setIsDynamic(is_dynamic); parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); } } @@ -3603,17 +3616,26 @@ F32 LLVOVolume::getReflectionProbeNearClip() const } } -LLReflectionProbeParams::EInfluenceVolumeType LLVOVolume::getReflectionProbeVolumeType() const +bool LLVOVolume::getReflectionProbeIsBox() const { const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); if (param_block) { - return param_block->getVolumeType(); + return param_block->getIsBox(); } - else + + return false; +} + +bool LLVOVolume::getReflectionProbeIsDynamic() const +{ + const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) { - return LLReflectionProbeParams::DEFAULT_VOLUME_TYPE; + return param_block->getIsDynamic(); } + + return false; } U32 LLVOVolume::getVolumeInterfaceID() const diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index ad7a2c5606..1ca6b49c7d 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -289,12 +289,14 @@ public: void setIsReflectionProbe(BOOL is_probe); void setReflectionProbeAmbiance(F32 ambiance); void setReflectionProbeNearClip(F32 near_clip); - void setReflectionProbeVolumeType(LLReflectionProbeParams::EInfluenceVolumeType volume_type); + void setReflectionProbeIsBox(bool is_box); + void setReflectionProbeIsDynamic(bool is_dynamic); BOOL isReflectionProbe() const override; F32 getReflectionProbeAmbiance() const; F32 getReflectionProbeNearClip() const; - LLReflectionProbeParams::EInfluenceVolumeType getReflectionProbeVolumeType() const; + bool getReflectionProbeIsBox() const; + bool getReflectionProbeIsDynamic() const; // Flexible Objects U32 getVolumeInterfaceID() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 20a21a685c..28dc3781ba 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6734,15 +6734,6 @@ void LLPipeline::toggleRenderType(U32 type) //static void LLPipeline::toggleRenderTypeControl(U32 type) { - U32 bit = (1< + + label="Select Invisible Objects" + name="Select Invisible Objects"> + control="SelectInvisibleObjects" /> + function="Tools.SelectInvisibleObjects" + parameter="invisible" /> Date: Fri, 10 Jun 2022 01:13:41 -0500 Subject: [PATCH 17/17] SL-17574 Add probe detail combo box to advanced graphics preferences. Fix spot light shadows not working in probes. --- indra/llrender/llrendertarget.cpp | 4 + indra/newview/app_settings/settings.xml | 11 + .../class3/deferred/reflectionProbeF.glsl | 13 +- indra/newview/llpanelvolume.cpp | 6 +- indra/newview/llreflectionmap.cpp | 26 +- indra/newview/llreflectionmap.h | 8 - indra/newview/llreflectionmapmanager.cpp | 63 ++- indra/newview/llreflectionmapmanager.h | 11 +- indra/newview/llspatialpartition.cpp | 17 - indra/newview/llspatialpartition.h | 3 - indra/newview/llviewercamera.h | 13 +- indra/newview/pipeline.cpp | 387 ++++++++++-------- indra/newview/pipeline.h | 16 +- .../floater_preferences_graphics_advanced.xml | 38 +- 14 files changed, 350 insertions(+), 266 deletions(-) diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 85d6209964..fa46e0f7d0 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -473,6 +473,8 @@ void LLRenderTarget::release() void LLRenderTarget::bindTarget() { + llassert(mFBO); + if (mFBO) { stop_glerror(); @@ -514,6 +516,7 @@ void LLRenderTarget::bindTarget() void LLRenderTarget::clear(U32 mask_in) { LL_PROFILE_GPU_ZONE("clear"); + llassert(mFBO); U32 mask = GL_COLOR_BUFFER_BIT; if (mUseDepth) { @@ -579,6 +582,7 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); + llassert(mFBO); if (!mFBO) { gGL.getTexUnit(0)->bind(this); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 327dfe6955..35a79f12de 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10280,6 +10280,17 @@ Value 2 + RenderReflectionProbeDetail + + Comment + Detail of reflections. + Persist + 1 + Type + S32 + Value + 1 + RenderReflectionProbeDrawDistance diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 3fd001e7f5..b3396baeba 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -74,6 +74,8 @@ bool isAbove(vec3 pos, vec4 plane) return (dot(plane.xyz, pos) + plane.w) > 0; } +int max_priority = 0; + // return true if probe at index i influences position pos bool shouldSampleProbe(int i, vec3 pos) { @@ -86,6 +88,8 @@ bool shouldSampleProbe(int i, vec3 pos) { return false; } + + max_priority = max(max_priority, -refIndex[i].w); } else { @@ -98,6 +102,8 @@ bool shouldSampleProbe(int i, vec3 pos) { //outside bounding sphere return false; } + + max_priority = max(max_priority, refIndex[i].w); } return true; @@ -343,8 +349,13 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) for (int idx = 0; idx < probeInfluences; ++idx) { int i = probeIndex[idx]; + if (refIndex[i].w < max_priority) + { + continue; + } float r = refSphere[i].w; // radius of sphere volume float p = float(abs(refIndex[i].w)); // priority + float rr = r*r; // radius squred float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down) vec3 delta = pos.xyz-refSphere[i].xyz; @@ -358,7 +369,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) float atten = 1.0-max(d2-r2, 0.0)/(rr-r2); w *= atten; - w *= p; // boost weight based on priority + //w *= p; // boost weight based on priority col += refcol*w*max(minweight, refParams[i].x); wsum += w; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index ddce22fa20..956539cd98 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -152,8 +152,6 @@ BOOL LLPanelVolume::postBuild() childSetCommitCallback("Probe Volume Type", onCommitProbe, this); childSetCommitCallback("Probe Ambiance", onCommitProbe, this); childSetCommitCallback("Probe Near Clip", onCommitProbe, this); - - } // PHYSICS Parameters @@ -695,7 +693,7 @@ void LLPanelVolume::clearCtrls() getChildView("Light Radius")->setEnabled(false); getChildView("Light Falloff")->setEnabled(false); - getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(false);; + getChildView("Reflection Probe")->setEnabled(false);; getChildView("Probe Volume Type")->setEnabled(false); getChildView("Probe Dynamic")->setEnabled(false); getChildView("Probe Ambiance")->setEnabled(false); @@ -746,7 +744,7 @@ void LLPanelVolume::sendIsReflectionProbe() } LLVOVolume* volobjp = (LLVOVolume*)objectp; - BOOL value = getChild("Reflection Probe Checkbox Ctrl")->getValue(); + BOOL value = getChild("Reflection Probe")->getValue(); volobjp->setIsReflectionProbe(value); LL_INFOS() << "update reflection probe sent" << LL_ENDL; } diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 39e0841fc5..500485fc70 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -54,28 +54,6 @@ void LLReflectionMap::update(U32 resolution, U32 face) gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic()); } -bool LLReflectionMap::shouldUpdate() -{ - const F32 TIMEOUT_INTERVAL = 30.f; // update no less than this often - const F32 RENDER_TIMEOUT = 1.f; // don't update if hasn't been used for rendering for this long - - if (mLastBindTime > gFrameTimeSeconds - RENDER_TIMEOUT) - { - if (mLastUpdateTime < gFrameTimeSeconds - TIMEOUT_INTERVAL) - { - return true; - } - } - - return false; -} - -void LLReflectionMap::dirty() -{ - mDirty = true; - mLastUpdateTime = gFrameTimeSeconds; -} - void LLReflectionMap::autoAdjustOrigin() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; @@ -245,7 +223,9 @@ F32 LLReflectionMap::getNearClip() bool LLReflectionMap::getIsDynamic() { - if (mViewerObject && mViewerObject->getVolume()) + if (gSavedSettings.getS32("RenderReflectionProbeDetail") > (S32) LLReflectionMapManager::DetailLevel::STATIC_ONLY && + mViewerObject && + mViewerObject->getVolume()) { return ((LLVOVolume*)mViewerObject)->getReflectionProbeIsDynamic(); } diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 071568e53c..cf0bc2ff27 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -43,12 +43,6 @@ public: // resolution - size of cube map to generate void update(U32 resolution, U32 face); - // return true if this probe should update *now* - bool shouldUpdate(); - - // Mark this reflection map as needing an update (resets last update time, so spamming this call will cause a cube map to never update) - void dirty(); - // for volume partition probes, try to place this probe in the best spot void autoAdjustOrigin(); @@ -104,7 +98,5 @@ public: // what priority should this probe have (higher is higher priority) U32 mPriority = 1; - - bool mDirty = true; }; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 60396b6c60..dc733687c3 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -96,11 +96,13 @@ void LLReflectionMapManager::update() mRenderTarget.allocate(targetRes, targetRes, color_fmt, use_depth_buffer, use_stencil_buffer, LLTexUnit::TT_RECT_TEXTURE); // hack to allocate render targets using gPipeline code + gCubeSnapshot = TRUE; auto* old_rt = gPipeline.mRT; gPipeline.mRT = &gProbeRT; gPipeline.allocateScreenBuffer(targetRes, targetRes); gPipeline.allocateShadowBuffer(targetRes, targetRes); gPipeline.mRT = old_rt; + gCubeSnapshot = FALSE; } if (mMipChain.empty()) @@ -154,6 +156,10 @@ void LLReflectionMapManager::update() bool did_update = false; + bool realtime = gSavedSettings.getS32("RenderReflectionProbeDetail") >= (S32)LLReflectionMapManager::DetailLevel::REALTIME; + + LLReflectionMap* closestDynamic = nullptr; + LLReflectionMap* oldestProbe = nullptr; if (mUpdatingProbe != nullptr) @@ -183,11 +189,30 @@ void LLReflectionMapManager::update() oldestProbe = probe; } + if (realtime && + closestDynamic == nullptr && + probe->mCubeArray.notNull() && + probe->getIsDynamic()) + { + closestDynamic = probe; + } + d.setSub(camera_pos, probe->mOrigin); probe->mDistance = d.getLength3().getF32()-probe->mRadius; } -#if 1 + if (realtime && closestDynamic != nullptr) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); + // update the closest dynamic probe realtime + closestDynamic->autoAdjustOrigin(); + for (U32 i = 0; i < 6; ++i) + { + updateProbeFace(closestDynamic, i); + } + } + + // switch to updating the next oldest probe if (!did_update && oldestProbe != nullptr) { LLReflectionMap* probe = oldestProbe; @@ -201,9 +226,7 @@ void LLReflectionMapManager::update() mUpdatingProbe = probe; doProbeUpdate(); - probe->mDirty = false; } -#endif // update distance to camera for all probes std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance()); @@ -214,7 +237,6 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group) LLReflectionMap* probe = new LLReflectionMap(); probe->mGroup = group; probe->mOrigin = group->getOctreeNode()->getCenter(); - probe->mDirty = true; if (gCubeSnapshot) { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update @@ -295,7 +317,6 @@ LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vo LLReflectionMap* probe = new LLReflectionMap(); probe->mViewerObject = vobj; probe->mOrigin.load3(vobj->getPositionAgent().mV); - probe->mDirty = true; if (gCubeSnapshot) { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update @@ -368,10 +389,23 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); + updateProbeFace(mUpdatingProbe, mUpdatingFace); + + if (++mUpdatingFace == 6) + { + updateNeighbors(mUpdatingProbe); + mUpdatingProbe = nullptr; + mUpdatingFace = 0; + } +} + +void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) +{ mRenderTarget.bindTarget(); + // hacky hot-swap of camera specific render targets auto* old_rt = gPipeline.mRT; gPipeline.mRT = &gProbeRT; - mUpdatingProbe->update(mRenderTarget.getWidth(), mUpdatingFace); + probe->update(mRenderTarget.getWidth(), face); gPipeline.mRT = old_rt; mRenderTarget.flush(); @@ -390,9 +424,9 @@ void LLReflectionMapManager::doProbeUpdate() gGL.loadIdentity(); gGL.flush(); - U32 res = LL_REFLECTION_PROBE_RESOLUTION*2; + U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2; - S32 mips = log2((F32) LL_REFLECTION_PROBE_RESOLUTION)+0.5f; + S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f; for (int i = 0; i < mMipChain.size(); ++i) { @@ -409,10 +443,10 @@ void LLReflectionMapManager::doProbeUpdate() } gGL.begin(gGL.QUADS); - + gGL.texCoord2f(0, 0); gGL.vertex2f(-1, -1); - + gGL.texCoord2f(res, 0); gGL.vertex2f(1, -1); @@ -431,7 +465,7 @@ void LLReflectionMapManager::doProbeUpdate() if (mip >= 0) { mTexture->bind(0); - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, mUpdatingProbe->mCubeIndex * 6 + mUpdatingFace, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); mTexture->unbind(); } mMipChain[i].flush(); @@ -443,13 +477,6 @@ void LLReflectionMapManager::doProbeUpdate() gReflectionMipProgram.unbind(); } - - if (++mUpdatingFace == 6) - { - updateNeighbors(mUpdatingProbe); - mUpdatingProbe = nullptr; - mUpdatingFace = 0; - } } void LLReflectionMapManager::rebuild() diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index bf963f3486..3b5cdc5520 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -46,6 +46,13 @@ class alignas(16) LLReflectionMapManager { LL_ALIGN_NEW public: + enum class DetailLevel + { + STATIC_ONLY = 0, + STATIC_AND_DYNAMIC, + REALTIME = 2 + }; + // allocate an environment map of the given resolution LLReflectionMapManager(); @@ -115,6 +122,9 @@ private: // perform an update on the currently updating Probe void doProbeUpdate(); + + // update the specified face of the specified probe + void updateProbeFace(LLReflectionMap* probe, U32 face); // list of active reflection maps std::vector > mProbes; @@ -133,6 +143,5 @@ private: LLReflectionMap* mUpdatingProbe = nullptr; U32 mUpdatingFace = 0; - }; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index a9e807e0f6..f445bc98eb 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -738,17 +738,8 @@ BOOL LLSpatialGroup::changeLOD() return FALSE; } -void LLSpatialGroup::dirtyReflectionProbe() -{ - if (mReflectionProbe != nullptr) - { - mReflectionProbe->dirty(); - } -} - void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry) { - dirtyReflectionProbe(); addObject((LLDrawable*)entry->getDrawable()); unbound(); setState(OBJECT_DIRTY); @@ -756,7 +747,6 @@ void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry) { - dirtyReflectionProbe(); removeObject((LLDrawable*)entry->getDrawable(), TRUE); LLViewerOctreeGroup::handleRemoval(node, entry); } @@ -793,8 +783,6 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c { LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL - dirtyReflectionProbe(); - if (child->getListenerCount() == 0) { new LLSpatialGroup(child, getSpatialPartition()); @@ -809,11 +797,6 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c assert_states_valid(this); } -void LLSpatialGroup::handleChildRemoval(const oct_node* parent, const oct_node* child) -{ - dirtyReflectionProbe(); -} - void LLSpatialGroup::destroyGL(bool keep_occlusion) { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index bebd8aec85..07d62be7af 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -333,7 +333,6 @@ public: virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face); virtual void handleDestruction(const TreeNode* node); virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); - virtual void handleChildRemoval(const oct_node* parent, const oct_node* child); public: LL_ALIGN_16(LLVector4a mViewAngle); @@ -341,8 +340,6 @@ public: F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3() - void dirtyReflectionProbe(); - protected: virtual ~LLSpatialGroup(); diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 549778a841..b5841772ed 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -47,15 +47,14 @@ public: typedef enum { CAMERA_WORLD = 0, - CAMERA_SHADOW0, - CAMERA_SHADOW1, - CAMERA_SHADOW2, - CAMERA_SHADOW3, - CAMERA_SHADOW4, - CAMERA_SHADOW5, + CAMERA_SUN_SHADOW0, + CAMERA_SUN_SHADOW1, + CAMERA_SUN_SHADOW2, + CAMERA_SUN_SHADOW3, + CAMERA_SPOT_SHADOW0, + CAMERA_SPOT_SHADOW1, CAMERA_WATER0, CAMERA_WATER1, - CAMERA_GI_SOURCE, NUM_CAMERAS } eCameraID; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 28dc3781ba..8bac5131cf 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -739,7 +739,8 @@ void LLPipeline::requestResizeShadowTexture() void LLPipeline::resizeShadowTexture() { - releaseShadowTargets(); + releaseSunShadowTargets(); + releaseSpotShadowTargets(); allocateShadowBuffer(mRT->width, mRT->height); gResizeShadowTexture = FALSE; } @@ -754,7 +755,8 @@ void LLPipeline::resizeScreenTexture() if (gResizeScreenTexture || (resX != mRT->screen.getWidth()) || (resY != mRT->screen.getHeight())) { releaseScreenBuffers(); - releaseShadowTargets(); + releaseSunShadowTargets(); + releaseSpotShadowTargets(); allocateScreenBuffer(resX,resY); gResizeScreenTexture = FALSE; } @@ -913,7 +915,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) { mRT->deferredLight.release(); - releaseShadowTargets(); + releaseSunShadowTargets(); + releaseSpotShadowTargets(); mRT->fxaaBuffer.release(); mRT->screen.release(); @@ -942,66 +945,66 @@ inline U32 BlurHappySize(U32 x, F32 scale) { return U32( x * scale + 16.0f) & ~0 bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (LLPipeline::sRenderDeferred) - { - S32 shadow_detail = RenderShadowDetail; + if (LLPipeline::sRenderDeferred) + { + S32 shadow_detail = RenderShadowDetail; - const U32 occlusion_divisor = 3; + const U32 occlusion_divisor = 3; - F32 scale = llmax(0.f,RenderShadowResolutionScale); - U32 sun_shadow_map_width = BlurHappySize(resX, scale); - U32 sun_shadow_map_height = BlurHappySize(resY, scale); + F32 scale = llmax(0.f, RenderShadowResolutionScale); + U32 sun_shadow_map_width = BlurHappySize(resX, scale); + U32 sun_shadow_map_height = BlurHappySize(resY, scale); - if (shadow_detail > 0) - { //allocate 4 sun shadow maps - for (U32 i = 0; i < 4; i++) - { - if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) + if (shadow_detail > 0) + { //allocate 4 sun shadow maps + for (U32 i = 0; i < 4; i++) + { + if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) { return false; } - if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width/occlusion_divisor, sun_shadow_map_height/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) + if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width / occlusion_divisor, sun_shadow_map_height / occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) { return false; } - } - } - else - { - for (U32 i = 0; i < 4; i++) - { - releaseShadowTarget(i); - } - } - - U32 width = (U32) (resX*scale); - U32 height = width; - - if (shadow_detail > 1) - { //allocate two spot shadow maps - U32 spot_shadow_map_width = width; - U32 spot_shadow_map_height = height; - for (U32 i = 4; i < 6; i++) - { - if (!mRT->shadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE)) - { - return false; - } - if (!mRT->shadowOcclusion[i].allocate(spot_shadow_map_width/occlusion_divisor, height/occlusion_divisor, 0, TRUE, FALSE)) - { - return false; - } - } + } } - else - { - for (U32 i = 4; i < 6; i++) - { - releaseShadowTarget(i); - } - } - } + else + { + for (U32 i = 0; i < 4; i++) + { + releaseSunShadowTarget(i); + } + } + + if (!gCubeSnapshot) // hack to not allocate spot shadow maps during ReflectionMapManager init + { + U32 width = (U32)(resX * scale); + U32 height = width; + + if (shadow_detail > 1) + { //allocate two spot shadow maps + U32 spot_shadow_map_width = width; + U32 spot_shadow_map_height = height; + for (U32 i = 0; i < 2; i++) + { + if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE)) + { + return false; + } + if (!mSpotShadowOcclusion[i].allocate(spot_shadow_map_width / occlusion_divisor, height / occlusion_divisor, 0, TRUE, FALSE)) + { + return false; + } + } + } + else + { + releaseSpotShadowTargets(); + } + } + } return true; } @@ -1175,7 +1178,8 @@ void LLPipeline::releaseLUTBuffers() void LLPipeline::releaseShadowBuffers() { - releaseShadowTargets(); + releaseSunShadowTargets(); + releaseSpotShadowTargets(); } void LLPipeline::releaseScreenBuffers() @@ -1191,20 +1195,33 @@ void LLPipeline::releaseScreenBuffers() } -void LLPipeline::releaseShadowTarget(U32 index) +void LLPipeline::releaseSunShadowTarget(U32 index) { + llassert(index < 4); mRT->shadow[index].release(); mRT->shadowOcclusion[index].release(); } -void LLPipeline::releaseShadowTargets() +void LLPipeline::releaseSunShadowTargets() { - for (U32 i = 0; i < 6; i++) + for (U32 i = 0; i < 4; i++) { - releaseShadowTarget(i); + releaseSunShadowTarget(i); } } +void LLPipeline::releaseSpotShadowTargets() +{ + if (!gCubeSnapshot) // hack to avoid freeing spot shadows during ReflectionMapManager init + { + for (U32 i = 0; i < 2; i++) + { + mSpotShadow[i].release(); + mSpotShadowOcclusion[i].release(); + } + } +} + void LLPipeline::createGLBuffers() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -8162,7 +8179,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ for (U32 i = 0; i < 4; i++) { - LLRenderTarget* shadow_target = getShadowTarget(i); + LLRenderTarget* shadow_target = getSunShadowTarget(i); if (shadow_target) { channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE); @@ -8170,7 +8187,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ if (channel > -1) { stop_glerror(); - gGL.getTexUnit(channel)->bind(getShadowTarget(i), TRUE); + gGL.getTexUnit(channel)->bind(getSunShadowTarget(i), TRUE); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC); gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); @@ -8182,27 +8199,27 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ } } - for (U32 i = 4; i < 6; i++) - { - channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i); - stop_glerror(); - if (channel > -1) - { - stop_glerror(); - LLRenderTarget* shadow_target = getShadowTarget(i); - if (shadow_target) - { - gGL.getTexUnit(channel)->bind(shadow_target, TRUE); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - stop_glerror(); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); - stop_glerror(); - } - } - } + for (U32 i = 4; i < 6; i++) + { + channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0 + i); + stop_glerror(); + if (channel > -1) + { + stop_glerror(); + LLRenderTarget* shadow_target = getSpotShadowTarget(i-4); + if (shadow_target) + { + gGL.getTexUnit(channel)->bind(shadow_target, TRUE); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + stop_glerror(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + stop_glerror(); + } + } + } stop_glerror(); @@ -8313,7 +8330,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV); shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV); shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].getHeight()); - shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mRT->shadow[4].getWidth(), mRT->shadow[4].getHeight()); + shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mSpotShadow[0].getWidth(), mSpotShadow[0].getHeight()); shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); @@ -9077,7 +9094,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f); } - if (!gCubeSnapshot) + //if (!gCubeSnapshot) { LLDrawable* potential = drawablep; //determine if this is a good light for casting shadows @@ -9668,7 +9685,9 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gDeferredShadowCubeProgram.bind(); } - LLRenderTarget& occlusion_target = mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - 1]; + LLRenderTarget& occlusion_target = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ? + mSpotShadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] : + mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0]; occlusion_target.bindTarget(); updateCull(shadow_cam, result); @@ -9812,7 +9831,9 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); - LLRenderTarget& occlusion_source = mRT->shadow[LLViewerCamera::sCurCameraID - 1]; + LLRenderTarget& occlusion_source = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ? + mSpotShadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] : + mRT->shadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0]; if (occlude > 1) { @@ -10087,11 +10108,18 @@ void LLPipeline::generateHighlight(LLCamera& camera) } } -LLRenderTarget* LLPipeline::getShadowTarget(U32 i) +LLRenderTarget* LLPipeline::getSunShadowTarget(U32 i) { + llassert(i < 4); return &mRT->shadow[i]; } +LLRenderTarget* LLPipeline::getSpotShadowTarget(U32 i) +{ + llassert(i < 2); + return &mSpotShadow[i]; +} + static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_RENDER("Spot Shadow Render"); @@ -10371,7 +10399,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadowFrustPoints[j].clear(); } - LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0+j); + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SUN_SHADOW0+j); //restore render matrices set_current_modelview(saved_view); @@ -10745,116 +10773,119 @@ void LLPipeline::generateSunShadow(LLCamera& camera) { if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates { - LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat(); - F32 fade_amt = gFrameIntervalSeconds.value() - * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0); + LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat(); + F32 fade_amt = gFrameIntervalSeconds.value() + * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0); - //update shadow targets - for (U32 i = 0; i < 2; i++) - { //for each current shadow - LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i); + //update shadow targets + for (U32 i = 0; i < 2; i++) + { //for each current shadow + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i); - if (mShadowSpotLight[i].notNull() && - (mShadowSpotLight[i] == mTargetShadowSpotLight[0] || - mShadowSpotLight[i] == mTargetShadowSpotLight[1])) - { //keep this spotlight - mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f); - } - else - { //fade out this light - mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f); - - if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull()) - { //faded out, grab one of the pending spots (whichever one isn't already taken) - if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2]) - { - mShadowSpotLight[i] = mTargetShadowSpotLight[0]; - } - else - { - mShadowSpotLight[i] = mTargetShadowSpotLight[1]; - } - } - } - } + if (mShadowSpotLight[i].notNull() && + (mShadowSpotLight[i] == mTargetShadowSpotLight[0] || + mShadowSpotLight[i] == mTargetShadowSpotLight[1])) + { //keep this spotlight + mSpotLightFade[i] = llmin(mSpotLightFade[i] + fade_amt, 1.f); + } + else + { //fade out this light + mSpotLightFade[i] = llmax(mSpotLightFade[i] - fade_amt, 0.f); - for (S32 i = 0; i < 2; i++) + if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull()) + { //faded out, grab one of the pending spots (whichever one isn't already taken) + if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i + 1) % 2]) + { + mShadowSpotLight[i] = mTargetShadowSpotLight[0]; + } + else + { + mShadowSpotLight[i] = mTargetShadowSpotLight[1]; + } + } + } + } + } + + for (S32 i = 0; i < 2; i++) + { + set_current_modelview(saved_view); + set_current_projection(saved_proj); + + if (mShadowSpotLight[i].isNull()) { - set_current_modelview(saved_view); - set_current_projection(saved_proj); + continue; + } - if (mShadowSpotLight[i].isNull()) - { - continue; - } + LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume(); - LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume(); + if (!volume) + { + mShadowSpotLight[i] = NULL; + continue; + } - if (!volume) - { - mShadowSpotLight[i] = NULL; - continue; - } + LLDrawable* drawable = mShadowSpotLight[i]; - LLDrawable* drawable = mShadowSpotLight[i]; + LLVector3 params = volume->getSpotLightParams(); + F32 fov = params.mV[0]; - LLVector3 params = volume->getSpotLightParams(); - F32 fov = params.mV[0]; + //get agent->light space matrix (modelview) + LLVector3 center = drawable->getPositionAgent(); + LLQuaternion quat = volume->getRenderRotation(); - //get agent->light space matrix (modelview) - LLVector3 center = drawable->getPositionAgent(); - LLQuaternion quat = volume->getRenderRotation(); + //get near clip plane + LLVector3 scale = volume->getScale(); + LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f); + at_axis *= quat; - //get near clip plane - LLVector3 scale = volume->getScale(); - LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f); - at_axis *= quat; + LLVector3 np = center + at_axis; + at_axis.normVec(); - LLVector3 np = center + at_axis; - at_axis.normVec(); + //get origin that has given fov for plane np, at_axis, and given scale + F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f); - //get origin that has given fov for plane np, at_axis, and given scale - F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f); + LLVector3 origin = np - at_axis * dist; - LLVector3 origin = np - at_axis * dist; + LLMatrix4 mat(quat, LLVector4(origin, 1.f)); - LLMatrix4 mat(quat, LLVector4(origin, 1.f)); + view[i + 4] = glh::matrix4f((F32*)mat.mMatrix); - view[i + 4] = glh::matrix4f((F32*)mat.mMatrix); + view[i + 4] = view[i + 4].inverse(); - view[i + 4] = view[i + 4].inverse(); + //get perspective matrix + F32 near_clip = dist + 0.01f; + F32 width = scale.mV[VX]; + F32 height = scale.mV[VY]; + F32 far_clip = dist + volume->getLightRadius() * 1.5f; - //get perspective matrix - F32 near_clip = dist + 0.01f; - F32 width = scale.mV[VX]; - F32 height = scale.mV[VY]; - F32 far_clip = dist + volume->getLightRadius() * 1.5f; + F32 fovy = fov * RAD_TO_DEG; + F32 aspect = width / height; - F32 fovy = fov * RAD_TO_DEG; - F32 aspect = width / height; + proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip); - proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip); + //translate and scale to from [-1, 1] to [0, 1] + glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, + 0.f, 0.5f, 0.f, 0.5f, + 0.f, 0.f, 0.5f, 0.5f, + 0.f, 0.f, 0.f, 1.f); - //translate and scale to from [-1, 1] to [0, 1] - glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, - 0.f, 0.5f, 0.f, 0.5f, - 0.f, 0.f, 0.5f, 0.5f, - 0.f, 0.f, 0.f, 1.f); + set_current_modelview(view[i + 4]); + set_current_projection(proj[i + 4]); - set_current_modelview(view[i + 4]); - set_current_projection(proj[i + 4]); + mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view; - mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view; + for (U32 j = 0; j < 16; j++) + { + gGLLastModelView[j] = mShadowModelview[i + 4].m[j]; + gGLLastProjection[j] = mShadowProjection[i + 4].m[j]; + } - for (U32 j = 0; j < 16; j++) - { - gGLLastModelView[j] = mShadowModelview[i + 4].m[j]; - gGLLastProjection[j] = mShadowProjection[i + 4].m[j]; - } - - mShadowModelview[i + 4] = view[i + 4]; - mShadowProjection[i + 4] = proj[i + 4]; + mShadowModelview[i + 4] = view[i + 4]; + mShadowProjection[i + 4] = proj[i + 4]; + if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates + { LLCamera shadow_cam = camera; shadow_cam.setFar(far_clip); shadow_cam.setOrigin(origin); @@ -10863,15 +10894,17 @@ void LLPipeline::generateSunShadow(LLCamera& camera) stop_glerror(); - mRT->shadow[i + 4].bindTarget(); - mRT->shadow[i + 4].getViewport(gGLViewport); - mRT->shadow[i + 4].clear(); + // + + mSpotShadow[i].bindTarget(); + mSpotShadow[i].getViewport(gGLViewport); + mSpotShadow[i].clear(); - U32 target_width = mRT->shadow[i + 4].getWidth(); + U32 target_width = mSpotShadow[i].getWidth(); static LLCullResult result[2]; - LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4); + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i); RenderSpotLight = drawable; @@ -10879,7 +10912,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) RenderSpotLight = nullptr; - mRT->shadow[i + 4].flush(); + mSpotShadow[i].flush(); } } } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index f4c55bde7d..f05b7aec8e 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -218,8 +218,9 @@ public: U32 addObject(LLViewerObject *obj); void enableShadows(const bool enable_shadows); - void releaseShadowTargets(); - void releaseShadowTarget(U32 index); + void releaseSpotShadowTargets(); + void releaseSunShadowTargets(); + void releaseSunShadowTarget(U32 index); // void setLocalLighting(const bool local_lighting); // bool isLocalLightingEnabled() const; @@ -304,7 +305,8 @@ public: void generateWaterReflection(LLCamera& camera); void generateSunShadow(LLCamera& camera); - LLRenderTarget* getShadowTarget(U32 i); + LLRenderTarget* getSunShadowTarget(U32 i); + LLRenderTarget* getSpotShadowTarget(U32 i); void generateHighlight(LLCamera& camera); void renderHighlight(const LLViewerObject* obj, F32 fade); @@ -660,12 +662,15 @@ public: LLRenderTarget deferredLight; //sun shadow map - LLRenderTarget shadow[6]; - LLRenderTarget shadowOcclusion[6]; + LLRenderTarget shadow[4]; + LLRenderTarget shadowOcclusion[4]; }; RenderTargetPack* mRT; + LLRenderTarget mSpotShadow[2]; + LLRenderTarget mSpotShadowOcclusion[2]; + LLRenderTarget mHighlight; LLRenderTarget mPhysicsDisplay; @@ -688,6 +693,7 @@ public: LLVector3 mShadowFrustOrigin[4]; LLCamera mShadowCamera[8]; LLVector3 mShadowExtents[4][2]; + // TODO : separate Sun Shadow and Spot Shadow matrices glh::matrix4f mSunShadowMatrix[6]; glh::matrix4f mShadowModelview[6]; glh::matrix4f mShadowProjection[6]; diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index d1e167df64..8e12a01c6f 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -863,8 +863,42 @@ name="2" value="2"/> - - + + Reflections: + + + + + + + +